abb-opencode-local-rag 0.1.0

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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.de.md +416 -0
  3. package/README.es.md +416 -0
  4. package/README.fr.md +416 -0
  5. package/README.md +491 -0
  6. package/README.pt-BR.md +416 -0
  7. package/README.zh-CN.md +416 -0
  8. package/dist/bin/install-skills.d.ts +20 -0
  9. package/dist/bin/install-skills.d.ts.map +1 -0
  10. package/dist/bin/install-skills.js +195 -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 +97 -0
  17. package/dist/chunker/semantic-chunker.d.ts.map +1 -0
  18. package/dist/chunker/semantic-chunker.js +294 -0
  19. package/dist/chunker/semantic-chunker.js.map +1 -0
  20. package/dist/chunker/sentence-splitter.d.ts +28 -0
  21. package/dist/chunker/sentence-splitter.d.ts.map +1 -0
  22. package/dist/chunker/sentence-splitter.js +219 -0
  23. package/dist/chunker/sentence-splitter.js.map +1 -0
  24. package/dist/cli/common.d.ts +65 -0
  25. package/dist/cli/common.d.ts.map +1 -0
  26. package/dist/cli/common.js +138 -0
  27. package/dist/cli/common.js.map +1 -0
  28. package/dist/cli/delete.d.ts +8 -0
  29. package/dist/cli/delete.d.ts.map +1 -0
  30. package/dist/cli/delete.js +173 -0
  31. package/dist/cli/delete.js.map +1 -0
  32. package/dist/cli/file-collection.d.ts +2 -0
  33. package/dist/cli/file-collection.d.ts.map +1 -0
  34. package/dist/cli/file-collection.js +53 -0
  35. package/dist/cli/file-collection.js.map +1 -0
  36. package/dist/cli/ingest.d.ts +100 -0
  37. package/dist/cli/ingest.d.ts.map +1 -0
  38. package/dist/cli/ingest.js +363 -0
  39. package/dist/cli/ingest.js.map +1 -0
  40. package/dist/cli/list.d.ts +35 -0
  41. package/dist/cli/list.d.ts.map +1 -0
  42. package/dist/cli/list.js +210 -0
  43. package/dist/cli/list.js.map +1 -0
  44. package/dist/cli/options.d.ts +100 -0
  45. package/dist/cli/options.d.ts.map +1 -0
  46. package/dist/cli/options.js +241 -0
  47. package/dist/cli/options.js.map +1 -0
  48. package/dist/cli/query.d.ts +24 -0
  49. package/dist/cli/query.d.ts.map +1 -0
  50. package/dist/cli/query.js +191 -0
  51. package/dist/cli/query.js.map +1 -0
  52. package/dist/cli/read-neighbors.d.ts +11 -0
  53. package/dist/cli/read-neighbors.d.ts.map +1 -0
  54. package/dist/cli/read-neighbors.js +224 -0
  55. package/dist/cli/read-neighbors.js.map +1 -0
  56. package/dist/cli/status.d.ts +8 -0
  57. package/dist/cli/status.d.ts.map +1 -0
  58. package/dist/cli/status.js +80 -0
  59. package/dist/cli/status.js.map +1 -0
  60. package/dist/cli/sync.d.ts +8 -0
  61. package/dist/cli/sync.d.ts.map +1 -0
  62. package/dist/cli/sync.js +244 -0
  63. package/dist/cli/sync.js.map +1 -0
  64. package/dist/cli-main.d.ts +12 -0
  65. package/dist/cli-main.d.ts.map +1 -0
  66. package/dist/cli-main.js +63 -0
  67. package/dist/cli-main.js.map +1 -0
  68. package/dist/embedder/index.d.ts +85 -0
  69. package/dist/embedder/index.d.ts.map +1 -0
  70. package/dist/embedder/index.js +284 -0
  71. package/dist/embedder/index.js.map +1 -0
  72. package/dist/features/list.d.ts +37 -0
  73. package/dist/features/list.d.ts.map +1 -0
  74. package/dist/features/list.js +40 -0
  75. package/dist/features/list.js.map +1 -0
  76. package/dist/features/sync.d.ts +207 -0
  77. package/dist/features/sync.d.ts.map +1 -0
  78. package/dist/features/sync.js +380 -0
  79. package/dist/features/sync.js.map +1 -0
  80. package/dist/index.d.ts +3 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +53 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/ingest/compute.d.ts +86 -0
  85. package/dist/ingest/compute.d.ts.map +1 -0
  86. package/dist/ingest/compute.js +177 -0
  87. package/dist/ingest/compute.js.map +1 -0
  88. package/dist/ingest/file.d.ts +27 -0
  89. package/dist/ingest/file.d.ts.map +1 -0
  90. package/dist/ingest/file.js +67 -0
  91. package/dist/ingest/file.js.map +1 -0
  92. package/dist/ingest/visual.d.ts +45 -0
  93. package/dist/ingest/visual.d.ts.map +1 -0
  94. package/dist/ingest/visual.js +234 -0
  95. package/dist/ingest/visual.js.map +1 -0
  96. package/dist/parser/docx-parser.d.ts +12 -0
  97. package/dist/parser/docx-parser.d.ts.map +1 -0
  98. package/dist/parser/docx-parser.js +328 -0
  99. package/dist/parser/docx-parser.js.map +1 -0
  100. package/dist/parser/html-parser.d.ts +18 -0
  101. package/dist/parser/html-parser.d.ts.map +1 -0
  102. package/dist/parser/html-parser.js +102 -0
  103. package/dist/parser/html-parser.js.map +1 -0
  104. package/dist/parser/index.d.ts +214 -0
  105. package/dist/parser/index.d.ts.map +1 -0
  106. package/dist/parser/index.js +454 -0
  107. package/dist/parser/index.js.map +1 -0
  108. package/dist/parser/pdf-extract.d.ts +81 -0
  109. package/dist/parser/pdf-extract.d.ts.map +1 -0
  110. package/dist/parser/pdf-extract.js +112 -0
  111. package/dist/parser/pdf-extract.js.map +1 -0
  112. package/dist/parser/pdf-filter.d.ts +117 -0
  113. package/dist/parser/pdf-filter.d.ts.map +1 -0
  114. package/dist/parser/pdf-filter.js +528 -0
  115. package/dist/parser/pdf-filter.js.map +1 -0
  116. package/dist/parser/title-extractor.d.ts +69 -0
  117. package/dist/parser/title-extractor.d.ts.map +1 -0
  118. package/dist/parser/title-extractor.js +145 -0
  119. package/dist/parser/title-extractor.js.map +1 -0
  120. package/dist/pdf-visual/captioner.d.ts +16 -0
  121. package/dist/pdf-visual/captioner.d.ts.map +1 -0
  122. package/dist/pdf-visual/captioner.js +63 -0
  123. package/dist/pdf-visual/captioner.js.map +1 -0
  124. package/dist/pdf-visual/captioners/fast.d.ts +7 -0
  125. package/dist/pdf-visual/captioners/fast.d.ts.map +1 -0
  126. package/dist/pdf-visual/captioners/fast.js +103 -0
  127. package/dist/pdf-visual/captioners/fast.js.map +1 -0
  128. package/dist/pdf-visual/captioners/quality.d.ts +7 -0
  129. package/dist/pdf-visual/captioners/quality.d.ts.map +1 -0
  130. package/dist/pdf-visual/captioners/quality.js +127 -0
  131. package/dist/pdf-visual/captioners/quality.js.map +1 -0
  132. package/dist/pdf-visual/captioners/shared.d.ts +44 -0
  133. package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
  134. package/dist/pdf-visual/captioners/shared.js +104 -0
  135. package/dist/pdf-visual/captioners/shared.js.map +1 -0
  136. package/dist/pdf-visual/detector.d.ts +9 -0
  137. package/dist/pdf-visual/detector.d.ts.map +1 -0
  138. package/dist/pdf-visual/detector.js +234 -0
  139. package/dist/pdf-visual/detector.js.map +1 -0
  140. package/dist/pdf-visual/index.d.ts +13 -0
  141. package/dist/pdf-visual/index.d.ts.map +1 -0
  142. package/dist/pdf-visual/index.js +45 -0
  143. package/dist/pdf-visual/index.js.map +1 -0
  144. package/dist/pdf-visual/renderer.d.ts +9 -0
  145. package/dist/pdf-visual/renderer.d.ts.map +1 -0
  146. package/dist/pdf-visual/renderer.js +177 -0
  147. package/dist/pdf-visual/renderer.js.map +1 -0
  148. package/dist/pdf-visual/types.d.ts +62 -0
  149. package/dist/pdf-visual/types.d.ts.map +1 -0
  150. package/dist/pdf-visual/types.js +32 -0
  151. package/dist/pdf-visual/types.js.map +1 -0
  152. package/dist/server/error-utils.d.ts +79 -0
  153. package/dist/server/error-utils.d.ts.map +1 -0
  154. package/dist/server/error-utils.js +148 -0
  155. package/dist/server/error-utils.js.map +1 -0
  156. package/dist/server/index.d.ts +258 -0
  157. package/dist/server/index.d.ts.map +1 -0
  158. package/dist/server/index.js +1104 -0
  159. package/dist/server/index.js.map +1 -0
  160. package/dist/server/list-scanner.d.ts +52 -0
  161. package/dist/server/list-scanner.d.ts.map +1 -0
  162. package/dist/server/list-scanner.js +72 -0
  163. package/dist/server/list-scanner.js.map +1 -0
  164. package/dist/server/tool-definitions.d.ts +8 -0
  165. package/dist/server/tool-definitions.d.ts.map +1 -0
  166. package/dist/server/tool-definitions.js +181 -0
  167. package/dist/server/tool-definitions.js.map +1 -0
  168. package/dist/server/tool-input.d.ts +37 -0
  169. package/dist/server/tool-input.d.ts.map +1 -0
  170. package/dist/server/tool-input.js +216 -0
  171. package/dist/server/tool-input.js.map +1 -0
  172. package/dist/server/types.d.ts +331 -0
  173. package/dist/server/types.d.ts.map +1 -0
  174. package/dist/server/types.js +3 -0
  175. package/dist/server/types.js.map +1 -0
  176. package/dist/server-main.d.ts +46 -0
  177. package/dist/server-main.d.ts.map +1 -0
  178. package/dist/server-main.js +242 -0
  179. package/dist/server-main.js.map +1 -0
  180. package/dist/utils/base-dirs.d.ts +212 -0
  181. package/dist/utils/base-dirs.d.ts.map +1 -0
  182. package/dist/utils/base-dirs.js +422 -0
  183. package/dist/utils/base-dirs.js.map +1 -0
  184. package/dist/utils/errors.d.ts +24 -0
  185. package/dist/utils/errors.d.ts.map +1 -0
  186. package/dist/utils/errors.js +53 -0
  187. package/dist/utils/errors.js.map +1 -0
  188. package/dist/utils/limits.d.ts +26 -0
  189. package/dist/utils/limits.d.ts.map +1 -0
  190. package/dist/utils/limits.js +28 -0
  191. package/dist/utils/limits.js.map +1 -0
  192. package/dist/utils/list-sources.d.ts +47 -0
  193. package/dist/utils/list-sources.d.ts.map +1 -0
  194. package/dist/utils/list-sources.js +50 -0
  195. package/dist/utils/list-sources.js.map +1 -0
  196. package/dist/utils/raw-data-utils.d.ts +131 -0
  197. package/dist/utils/raw-data-utils.d.ts.map +1 -0
  198. package/dist/utils/raw-data-utils.js +255 -0
  199. package/dist/utils/raw-data-utils.js.map +1 -0
  200. package/dist/utils/scan.d.ts +126 -0
  201. package/dist/utils/scan.d.ts.map +1 -0
  202. package/dist/utils/scan.js +221 -0
  203. package/dist/utils/scan.js.map +1 -0
  204. package/dist/utils/scope-match.d.ts +43 -0
  205. package/dist/utils/scope-match.d.ts.map +1 -0
  206. package/dist/utils/scope-match.js +87 -0
  207. package/dist/utils/scope-match.js.map +1 -0
  208. package/dist/utils/sensitive-path.d.ts +23 -0
  209. package/dist/utils/sensitive-path.d.ts.map +1 -0
  210. package/dist/utils/sensitive-path.js +91 -0
  211. package/dist/utils/sensitive-path.js.map +1 -0
  212. package/dist/utils/sync-path-key.d.ts +20 -0
  213. package/dist/utils/sync-path-key.d.ts.map +1 -0
  214. package/dist/utils/sync-path-key.js +33 -0
  215. package/dist/utils/sync-path-key.js.map +1 -0
  216. package/dist/vectordb/index.d.ts +168 -0
  217. package/dist/vectordb/index.d.ts.map +1 -0
  218. package/dist/vectordb/index.js +619 -0
  219. package/dist/vectordb/index.js.map +1 -0
  220. package/dist/vectordb/search-filters.d.ts +39 -0
  221. package/dist/vectordb/search-filters.d.ts.map +1 -0
  222. package/dist/vectordb/search-filters.js +136 -0
  223. package/dist/vectordb/search-filters.js.map +1 -0
  224. package/dist/vectordb/types.d.ts +196 -0
  225. package/dist/vectordb/types.d.ts.map +1 -0
  226. package/dist/vectordb/types.js +224 -0
  227. package/dist/vectordb/types.js.map +1 -0
  228. package/package.json +105 -0
  229. package/skills/mcp-local-rag/SKILL.md +308 -0
  230. package/skills/mcp-local-rag/references/cli-reference.md +175 -0
  231. package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
  232. package/skills/mcp-local-rag/references/query-optimization.md +57 -0
  233. package/skills/mcp-local-rag/references/result-refinement.md +56 -0
@@ -0,0 +1,50 @@
1
+ // Pure `sources` classifier shared by the MCP `list_files` handler
2
+ // (`src/server/index.ts`) and the `list` CLI (`src/cli/list.ts`). Extracted
3
+ // from the byte-for-byte-identical inline blocks in both surfaces so the
4
+ // raw-data / real-file scope branch lives in one place, mirroring the
5
+ // drift-avoidance rationale behind the shared `scope-match.ts` matcher.
6
+ //
7
+ // `sources` are ingested entries whose identity key matched no scanned file:
8
+ // content ingested via `ingest_data` (raw-data paths) plus orphaned DB entries
9
+ // for real files not currently on disk under a scanned root.
10
+ import { extractSourceFromPath, isManagedRawDataPath } from './raw-data-utils.js';
11
+ import { matchesAnyScope } from './scope-match.js';
12
+ /**
13
+ * Classify the ingested entries that matched no scanned file into `sources`.
14
+ *
15
+ * Base filter (always): keep only entries whose `key` is absent from
16
+ * `matchedKeys`.
17
+ *
18
+ * When `scope` is present (non-empty): raw-data entries
19
+ * Managed raw-data entries have no filesystem path under a base directory, so
20
+ * they are always emitted regardless of scope; real-file entries are kept only
21
+ * when their stored `filePath` is under scope (`matchesAnyScope`) — a real-file
22
+ * entry outside scope is dropped so it appears in neither `files[]` (already
23
+ * pruned from the scan) nor `sources[]` (no orphan misclassification), while an
24
+ * unmatched real-file entry under scope remains an orphan source.
25
+ *
26
+ * When `scope` is absent (or empty): behavior is unchanged from the pre-extraction
27
+ * inline block — every unmatched entry is emitted, raw-data as `{ source }` when
28
+ * `extractSourceFromPath` yields one, else as `{ filePath }`.
29
+ */
30
+ export function classifyIngestedSources(ingestedKeyed, matchedKeys, dbPath, scope) {
31
+ const scopePrefixes = scope && scope.length > 0 ? scope : undefined;
32
+ return ingestedKeyed
33
+ .filter(({ key }) => !matchedKeys.has(key))
34
+ .filter(({ entry }) => {
35
+ if (!scopePrefixes)
36
+ return true;
37
+ // Raw-data sources are exempt from scope; real-file entries respect it.
38
+ return (isManagedRawDataPath(entry.filePath, dbPath) ||
39
+ matchesAnyScope(entry.filePath, scopePrefixes));
40
+ })
41
+ .map(({ entry }) => {
42
+ if (isManagedRawDataPath(entry.filePath, dbPath)) {
43
+ const source = extractSourceFromPath(entry.filePath);
44
+ if (source)
45
+ return { source, chunkCount: entry.chunkCount, timestamp: entry.timestamp };
46
+ }
47
+ return { filePath: entry.filePath, chunkCount: entry.chunkCount, timestamp: entry.timestamp };
48
+ });
49
+ }
50
+ //# sourceMappingURL=list-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-sources.js","sourceRoot":"","sources":["../../src/utils/list-sources.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,4EAA4E;AAC5E,yEAAyE;AACzE,sEAAsE;AACtE,wEAAwE;AACxE,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,6DAA6D;AAE7D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAqBlD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,uBAAuB,CACrC,aAA4C,EAC5C,WAAgC,EAChC,MAAc,EACd,KAAgB;IAEhB,MAAM,aAAa,GAAG,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IAEnE,OAAO,aAAa;SACjB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SAC1C,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;QACpB,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAA;QAC/B,wEAAwE;QACxE,OAAO,CACL,oBAAoB,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC5C,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,CAC/C,CAAA;IACH,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;QACjB,IAAI,oBAAoB,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YACjD,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YACpD,IAAI,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAA;QACzF,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAA;IAC/F,CAAC,CAAC,CAAA;AACN,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Encode string to URL-safe base64 (base64url)
3
+ * - Replaces + with -
4
+ * - Replaces / with _
5
+ * - Removes padding (=)
6
+ *
7
+ * @param str - String to encode
8
+ * @returns URL-safe base64 encoded string
9
+ */
10
+ export declare function encodeBase64Url(str: string): string;
11
+ /**
12
+ * Decode URL-safe base64 (base64url) to string
13
+ *
14
+ * @param base64url - URL-safe base64 encoded string
15
+ * @returns Decoded string
16
+ */
17
+ export declare function decodeBase64Url(base64url: string): string;
18
+ /**
19
+ * Normalize source URL by removing query string and fragment
20
+ * Only normalizes HTTP(S) URLs. Other sources (e.g., "clipboard://...") are returned as-is
21
+ *
22
+ * @param source - Source identifier (URL or custom ID)
23
+ * @returns Normalized source
24
+ */
25
+ export declare function normalizeSource(source: string): string;
26
+ /** Formats accepted by ingest_data at runtime and in its public schema. */
27
+ export declare const CONTENT_FORMATS: readonly ['text', 'html', 'markdown'];
28
+ export type ContentFormat = (typeof CONTENT_FORMATS)[number];
29
+ /**
30
+ * Get raw-data directory path
31
+ *
32
+ * @param dbPath - LanceDB database path
33
+ * @returns Raw-data directory path
34
+ */
35
+ export declare function getRawDataDir(dbPath: string): string;
36
+ /**
37
+ * Generate raw-data file path from source and format
38
+ * Path format: {dbPath}/raw-data/{base64url(normalizedSource)}.{ext}
39
+ *
40
+ * @param dbPath - LanceDB database path
41
+ * @param source - Source identifier (URL or custom ID)
42
+ * @param format - Content format
43
+ * @returns Generated file path
44
+ */
45
+ export declare function generateRawDataPath(dbPath: string, source: string): string;
46
+ /**
47
+ * Save content to raw-data directory
48
+ * Creates directory if it doesn't exist
49
+ *
50
+ * @param dbPath - LanceDB database path
51
+ * @param source - Source identifier (URL or custom ID)
52
+ * @param content - Content to save
53
+ * @param format - Content format
54
+ * @returns Saved file path
55
+ */
56
+ export declare function saveRawData(dbPath: string, source: string, content: string): Promise<string>;
57
+ /** True only for managed raw-data content files under this database. */
58
+ export declare function isManagedRawDataPath(filePath: string, dbPath: string): boolean;
59
+ /**
60
+ * Lexical containment in `<dbPath>/raw-data/`. Safe for cleanup gates
61
+ * (`unlink` does not follow symlinks). Use {@link isPathInRawDataDir}
62
+ * when the result controls `readFile`.
63
+ */
64
+ export declare function isPathInRawDataDirLexical(filePath: string, dbPath: string): boolean;
65
+ /**
66
+ * Lexical containment plus `realpath` so a symlink under raw-data
67
+ * pointing outside cannot route a read through the raw-data fast-path.
68
+ * Fail-closed on `realpath` errors.
69
+ */
70
+ export declare function isPathInRawDataDir(filePath: string, dbPath: string): Promise<boolean>;
71
+ /**
72
+ * Extract original source from raw-data file path
73
+ * Returns null if not a raw-data path
74
+ *
75
+ * @param filePath - Raw-data file path
76
+ * @returns Original source or null
77
+ */
78
+ export declare function extractSourceFromPath(filePath: string): string | null;
79
+ /**
80
+ * Metadata stored alongside each raw-data .md file as a .meta.json sidecar
81
+ */
82
+ export interface RawDataMeta {
83
+ title: string | null;
84
+ source: string;
85
+ format: ContentFormat;
86
+ }
87
+ /**
88
+ * Generate the .meta.json sidecar path for a given .md file path
89
+ * Replaces the trailing `.md` extension with `.meta.json`
90
+ *
91
+ * @param mdPath - Path to the .md raw-data file
92
+ * @returns Path to the corresponding .meta.json file
93
+ */
94
+ export declare function generateMetaJsonPath(mdPath: string): string;
95
+ /**
96
+ * Save metadata as a JSON sidecar file alongside a raw-data .md file
97
+ *
98
+ * @param mdPath - Path to the .md raw-data file
99
+ * @param meta - Metadata to persist
100
+ */
101
+ export declare function saveMetaJson(mdPath: string, meta: RawDataMeta): Promise<void>;
102
+ /**
103
+ * Load metadata from a .meta.json sidecar file
104
+ * Returns null when the sidecar file does not exist (ENOENT).
105
+ * All other read errors are re-thrown (fail-fast).
106
+ *
107
+ * @param mdPath - Path to the .md raw-data file
108
+ * @returns Parsed metadata or null if file does not exist
109
+ */
110
+ export declare function loadMetaJson(mdPath: string): Promise<RawDataMeta | null>;
111
+ /**
112
+ * True when a filesystem error means the target path does not exist.
113
+ */
114
+ export declare function isEnoent(error: unknown): boolean;
115
+ /**
116
+ * Pre-unlink existence of the on-disk raw-data artifacts for a target .md
117
+ * path: the raw-data file itself and its .meta.json sidecar.
118
+ */
119
+ export interface RawDataArtifactExistence {
120
+ rawDataExisted: boolean;
121
+ metaExisted: boolean;
122
+ }
123
+ /**
124
+ * Report which raw-data artifacts exist for a target path. Single source for
125
+ * the delete `existed` signal so the MCP server and CLI delete paths cannot
126
+ * drift. Call BEFORE unlinking — it reports pre-unlink state.
127
+ *
128
+ * @param targetPath - Raw-data .md file path
129
+ */
130
+ export declare function checkRawDataArtifacts(targetPath: string): Promise<RawDataArtifactExistence>;
131
+ //# sourceMappingURL=raw-data-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-data-utils.d.ts","sourceRoot":"","sources":["../../src/utils/raw-data-utils.ts"],"names":[],"mappings":"AAUA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUzD;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAatD;AAMD,2EAA2E;AAC3E,eAAO,MAAM,eAAe,YAAI,MAAM,EAAE,MAAM,EAAE,UAAU,CAAU,CAAA;AACpE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAQ5D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK1E;AAMD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAUjB;AAMD,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAI9E;AAUD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3F;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBrE;AAMD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,aAAa,CAAA;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnF;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAW9E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIhD;AAkBD;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,OAAO,CAAA;IACvB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAIjG"}
@@ -0,0 +1,255 @@
1
+ // Raw Data Utilities for ingest_data tool
2
+ // Handles: base64url encoding, source normalization, file saving, source extraction
3
+ import { access, mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
4
+ import { basename, dirname, join, resolve, sep } from 'node:path';
5
+ // ============================================
6
+ // Base64URL Encoding/Decoding
7
+ // ============================================
8
+ /**
9
+ * Encode string to URL-safe base64 (base64url)
10
+ * - Replaces + with -
11
+ * - Replaces / with _
12
+ * - Removes padding (=)
13
+ *
14
+ * @param str - String to encode
15
+ * @returns URL-safe base64 encoded string
16
+ */
17
+ export function encodeBase64Url(str) {
18
+ return Buffer.from(str, 'utf-8')
19
+ .toString('base64')
20
+ .replace(/\+/g, '-')
21
+ .replace(/\//g, '_')
22
+ .replace(/=+$/, '');
23
+ }
24
+ /**
25
+ * Decode URL-safe base64 (base64url) to string
26
+ *
27
+ * @param base64url - URL-safe base64 encoded string
28
+ * @returns Decoded string
29
+ */
30
+ export function decodeBase64Url(base64url) {
31
+ // Convert base64url to standard base64
32
+ let base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');
33
+ // Add padding if needed
34
+ while (base64.length % 4 !== 0) {
35
+ base64 += '=';
36
+ }
37
+ return Buffer.from(base64, 'base64').toString('utf-8');
38
+ }
39
+ // ============================================
40
+ // Source Normalization
41
+ // ============================================
42
+ /**
43
+ * Normalize source URL by removing query string and fragment
44
+ * Only normalizes HTTP(S) URLs. Other sources (e.g., "clipboard://...") are returned as-is
45
+ *
46
+ * @param source - Source identifier (URL or custom ID)
47
+ * @returns Normalized source
48
+ */
49
+ export function normalizeSource(source) {
50
+ try {
51
+ const parsed = new URL(source);
52
+ // Only normalize HTTP(S) URLs
53
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
54
+ return `${parsed.origin}${parsed.pathname}`;
55
+ }
56
+ // Non-HTTP URLs (clipboard://, etc.) are returned as-is
57
+ return source;
58
+ }
59
+ catch {
60
+ // Not a valid URL, return as-is
61
+ return source;
62
+ }
63
+ }
64
+ // ============================================
65
+ // Format Utilities
66
+ // ============================================
67
+ /** Formats accepted by ingest_data at runtime and in its public schema. */
68
+ export const CONTENT_FORMATS = ['text', 'html', 'markdown'];
69
+ const RAW_DATA_EXTENSION = 'md';
70
+ // ============================================
71
+ // Path Generation
72
+ // ============================================
73
+ /**
74
+ * Get raw-data directory path
75
+ *
76
+ * @param dbPath - LanceDB database path
77
+ * @returns Raw-data directory path
78
+ */
79
+ export function getRawDataDir(dbPath) {
80
+ return join(dbPath, 'raw-data');
81
+ }
82
+ /**
83
+ * Generate raw-data file path from source and format
84
+ * Path format: {dbPath}/raw-data/{base64url(normalizedSource)}.{ext}
85
+ *
86
+ * @param dbPath - LanceDB database path
87
+ * @param source - Source identifier (URL or custom ID)
88
+ * @param format - Content format
89
+ * @returns Generated file path
90
+ */
91
+ export function generateRawDataPath(dbPath, source) {
92
+ const normalizedSource = normalizeSource(source);
93
+ const encoded = encodeBase64Url(normalizedSource);
94
+ // Use resolve to ensure absolute path (required by validateFilePath)
95
+ return resolve(getRawDataDir(dbPath), `${encoded}.${RAW_DATA_EXTENSION}`);
96
+ }
97
+ // ============================================
98
+ // File Operations
99
+ // ============================================
100
+ /**
101
+ * Save content to raw-data directory
102
+ * Creates directory if it doesn't exist
103
+ *
104
+ * @param dbPath - LanceDB database path
105
+ * @param source - Source identifier (URL or custom ID)
106
+ * @param content - Content to save
107
+ * @param format - Content format
108
+ * @returns Saved file path
109
+ */
110
+ export async function saveRawData(dbPath, source, content) {
111
+ const filePath = generateRawDataPath(dbPath, source);
112
+ // Ensure directory exists
113
+ await mkdir(dirname(filePath), { recursive: true });
114
+ // Write content to file
115
+ await writeFile(filePath, content, 'utf-8');
116
+ return filePath;
117
+ }
118
+ // ============================================
119
+ // Path Detection and Source Extraction
120
+ // ============================================
121
+ /** True only for managed raw-data content files under this database. */
122
+ export function isManagedRawDataPath(filePath, dbPath) {
123
+ return (isPathInRawDataDirLexical(filePath, dbPath) && /^[A-Za-z0-9_-]+\.md$/.test(basename(filePath)));
124
+ }
125
+ /**
126
+ * Case-normalize a path for prefix containment. Windows filesystems are
127
+ * case-insensitive by default, so the boundary check must mirror that.
128
+ */
129
+ function caseNormalize(p) {
130
+ return process.platform === 'win32' ? p.toLowerCase() : p;
131
+ }
132
+ /**
133
+ * Lexical containment in `<dbPath>/raw-data/`. Safe for cleanup gates
134
+ * (`unlink` does not follow symlinks). Use {@link isPathInRawDataDir}
135
+ * when the result controls `readFile`.
136
+ */
137
+ export function isPathInRawDataDirLexical(filePath, dbPath) {
138
+ const target = caseNormalize(resolve(filePath));
139
+ const rawDir = caseNormalize(resolve(getRawDataDir(dbPath)));
140
+ return target === rawDir || target.startsWith(rawDir + sep);
141
+ }
142
+ /**
143
+ * Lexical containment plus `realpath` so a symlink under raw-data
144
+ * pointing outside cannot route a read through the raw-data fast-path.
145
+ * Fail-closed on `realpath` errors.
146
+ */
147
+ export async function isPathInRawDataDir(filePath, dbPath) {
148
+ if (!isPathInRawDataDirLexical(filePath, dbPath))
149
+ return false;
150
+ try {
151
+ const realTarget = caseNormalize(await realpath(resolve(filePath)));
152
+ const realRaw = caseNormalize(await realpath(resolve(getRawDataDir(dbPath))));
153
+ return realTarget === realRaw || realTarget.startsWith(realRaw + sep);
154
+ }
155
+ catch {
156
+ return false;
157
+ }
158
+ }
159
+ /**
160
+ * Extract original source from raw-data file path
161
+ * Returns null if not a raw-data path
162
+ *
163
+ * @param filePath - Raw-data file path
164
+ * @returns Original source or null
165
+ */
166
+ export function extractSourceFromPath(filePath) {
167
+ const normalized = filePath.replace(/\\/g, '/');
168
+ const rawDataMarker = '/raw-data/';
169
+ const rawDataIndex = normalized.indexOf(rawDataMarker);
170
+ if (rawDataIndex === -1) {
171
+ return null;
172
+ }
173
+ const fileName = filePath.slice(rawDataIndex + rawDataMarker.length);
174
+ const dotIndex = fileName.lastIndexOf('.');
175
+ if (dotIndex === -1) {
176
+ return null;
177
+ }
178
+ const encoded = fileName.slice(0, dotIndex);
179
+ return decodeBase64Url(encoded);
180
+ }
181
+ /**
182
+ * Generate the .meta.json sidecar path for a given .md file path
183
+ * Replaces the trailing `.md` extension with `.meta.json`
184
+ *
185
+ * @param mdPath - Path to the .md raw-data file
186
+ * @returns Path to the corresponding .meta.json file
187
+ */
188
+ export function generateMetaJsonPath(mdPath) {
189
+ return mdPath.replace(/\.md$/, '.meta.json');
190
+ }
191
+ /**
192
+ * Save metadata as a JSON sidecar file alongside a raw-data .md file
193
+ *
194
+ * @param mdPath - Path to the .md raw-data file
195
+ * @param meta - Metadata to persist
196
+ */
197
+ export async function saveMetaJson(mdPath, meta) {
198
+ const metaPath = generateMetaJsonPath(mdPath);
199
+ await writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
200
+ }
201
+ /**
202
+ * Load metadata from a .meta.json sidecar file
203
+ * Returns null when the sidecar file does not exist (ENOENT).
204
+ * All other read errors are re-thrown (fail-fast).
205
+ *
206
+ * @param mdPath - Path to the .md raw-data file
207
+ * @returns Parsed metadata or null if file does not exist
208
+ */
209
+ export async function loadMetaJson(mdPath) {
210
+ const metaPath = generateMetaJsonPath(mdPath);
211
+ try {
212
+ const content = await readFile(metaPath, 'utf-8');
213
+ return JSON.parse(content);
214
+ }
215
+ catch (error) {
216
+ if (isEnoent(error)) {
217
+ return null;
218
+ }
219
+ throw error;
220
+ }
221
+ }
222
+ /**
223
+ * True when a filesystem error means the target path does not exist.
224
+ */
225
+ export function isEnoent(error) {
226
+ return (error instanceof Error && 'code' in error && error.code === 'ENOENT');
227
+ }
228
+ // ============================================
229
+ // Raw-Data Artifact Existence
230
+ // ============================================
231
+ /**
232
+ * Whether a path exists. access()-based, never throws.
233
+ */
234
+ async function pathExists(path) {
235
+ try {
236
+ await access(path);
237
+ return true;
238
+ }
239
+ catch {
240
+ return false;
241
+ }
242
+ }
243
+ /**
244
+ * Report which raw-data artifacts exist for a target path. Single source for
245
+ * the delete `existed` signal so the MCP server and CLI delete paths cannot
246
+ * drift. Call BEFORE unlinking — it reports pre-unlink state.
247
+ *
248
+ * @param targetPath - Raw-data .md file path
249
+ */
250
+ export async function checkRawDataArtifacts(targetPath) {
251
+ const rawDataExisted = await pathExists(targetPath);
252
+ const metaExisted = await pathExists(generateMetaJsonPath(targetPath));
253
+ return { rawDataExisted, metaExisted };
254
+ }
255
+ //# sourceMappingURL=raw-data-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-data-utils.js","sourceRoot":"","sources":["../../src/utils/raw-data-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Canonical identity key for the `list`/`list_files` cross-reference: a file's
3
+ * realpath, falling back to the input path when realpath fails (orphaned or
4
+ * raw-data entries). Matching ingested DB entries against scanned files by this
5
+ * key recognizes the same physical file across symlinked spellings (prefix or
6
+ * alias). Storage, lookup, and display still use the normal resolve() path —
7
+ * realpath here is the file-identity comparison, not a user-facing value.
8
+ */
9
+ export declare function realpathForMatch(filePath: string): Promise<string>;
10
+ /**
11
+ * Canonical form of one explicitly requested path: its parent chain resolved
12
+ * through symbolic links, with the final component appended verbatim. `null` when
13
+ * the parent chain cannot be resolved at all — absent, or a directory this
14
+ * process may not traverse — which a caller must treat as "not contained",
15
+ * because telling those cases apart would report the state of paths outside its
16
+ * configured roots.
17
+ *
18
+ * Only the parent chain is resolved, because the requested entry itself is judged
19
+ * by {@link classifyRequestedPath}'s `lstat`: a symbolic link named directly
20
+ * inside a root is an in-root entry that is refused as a link, not a path to be
21
+ * reported by whatever it points at.
22
+ *
23
+ * `realpath` here is the containment (security) boundary, the same role it plays
24
+ * in `DocumentParser.validateFilePath` — never a spelling anything is stored,
25
+ * looked up, or displayed under. Those stay `resolve()`-only.
26
+ */
27
+ export declare function canonicalizeRequestedPath(path: string): Promise<string | null>;
28
+ /** Why the collect predicates below refuse a path. */
29
+ export type ScanRejection =
30
+ /** A symbolic link, which is never followed. */
31
+ 'symlink'
32
+ /** Under a configured excluded prefix (the database or cache directory). */
33
+ | 'excluded'
34
+ /** A regular file whose extension is not a supported document type. */
35
+ | 'unsupported'
36
+ /** Neither a regular file nor a directory (socket, FIFO, device, …). */
37
+ | 'irregular';
38
+ /** What a path is, once the collect predicates have judged it. */
39
+ export type ScanEntryKind = 'file' | 'directory' | ScanRejection;
40
+ /** The `Dirent` / `Stats` subset the collect predicates read. */
41
+ interface EntryTypeFacts {
42
+ isSymbolicLink(): boolean;
43
+ isDirectory(): boolean;
44
+ isFile(): boolean;
45
+ }
46
+ /**
47
+ * The collect predicates of {@link bfsCollectSupportedFiles} as one decision, so
48
+ * a discovered directory entry and an explicitly requested path
49
+ * ({@link classifyRequestedPath}) are judged by exactly the same rules instead of
50
+ * by two implementations that can drift.
51
+ *
52
+ * Evaluation order is part of the contract and matches the walk: a symbolic link
53
+ * is reported as a link even under an excluded prefix, and a directory is
54
+ * accepted without any extension test.
55
+ *
56
+ * `platform` is a parameter rather than a direct `process.platform` read — the
57
+ * same reason `toSyncPathKey` takes one: the Windows exclusion semantics
58
+ * ({@link isUnderExcludedPrefix}) must be provable on a macOS/Linux machine. The
59
+ * default leaves every call site unchanged.
60
+ *
61
+ * Both `Dirent` (from `readdir`) and `Stats` (from `lstat`) satisfy
62
+ * {@link EntryTypeFacts} structurally.
63
+ */
64
+ export declare function classifyScanEntry(fullPath: string, entry: EntryTypeFacts, excludePaths: readonly string[], platform?: NodeJS.Platform): ScanEntryKind;
65
+ /**
66
+ * Classify one explicitly requested path with {@link classifyScanEntry}, so a
67
+ * path a caller names is subject to the same predicates as a path the walker
68
+ * discovers.
69
+ *
70
+ * `lstat` rather than `stat`, so a symbolic link is reported as a link instead of
71
+ * as whatever it points at; and `lstat` rather than any read, so a caller can
72
+ * refuse the path before its bytes cost anything — reading a FIFO blocks forever,
73
+ * and reading through a link reaches outside the configured roots.
74
+ *
75
+ * Any stat failure is `'missing'`: an unreachable path and an absent one are the
76
+ * same non-answer to "what is here".
77
+ */
78
+ export declare function classifyRequestedPath(path: string, excludePaths: readonly string[], platform?: NodeJS.Platform): Promise<ScanEntryKind | 'missing'>;
79
+ /** A directory that could not be read during the scan. */
80
+ export interface UnreadableDir {
81
+ dirPath: string;
82
+ /** Node error `code` (e.g. `EACCES`), or `'UNKNOWN'` when unavailable. */
83
+ code: string;
84
+ }
85
+ /** Structured result of a bounded directory scan. */
86
+ export interface DirScanResult {
87
+ /** Supported files found under the root, in BFS-discovery order (unsorted). */
88
+ files: string[];
89
+ /** Directories skipped because `readdir` failed (caller decides how to warn). */
90
+ unreadableDirs: UnreadableDir[];
91
+ /**
92
+ * Each entry is the first unvisited directory of a branch pruned for
93
+ * exceeding `maxDepth` — the directory that was reached but never read. That
94
+ * path and every descendant of it is unobserved by this scan; its ancestors
95
+ * and fully visited siblings are not listed.
96
+ */
97
+ depthLimitedDirs: string[];
98
+ /** Full paths of directory entries skipped because they are symbolic links. */
99
+ skippedSymlinks: string[];
100
+ /** True if any branch was pruned for exceeding `maxDepth`. */
101
+ depthLimited: boolean;
102
+ }
103
+ /**
104
+ * Bounded BFS scan of a single root, collecting every supported file up to
105
+ * `maxDepth` levels deep, counted from `rootPath` itself. Symlinks are skipped
106
+ * (never followed) and recorded in `skippedSymlinks`; paths under any
107
+ * `excludePaths` prefix are filtered out. A per-directory `readdir` failure is
108
+ * captured into `unreadableDirs` and does not abort the scan (best-effort per
109
+ * directory); a branch pruned at `maxDepth` is captured into `depthLimitedDirs`.
110
+ *
111
+ * When `scope` is provided (non-empty), the predicate is pushed into the
112
+ * traversal: a directory is visited only if it is in-scope or an ancestor of
113
+ * some scope prefix, and a file is collected only if it is in-scope. A root that
114
+ * intersects no prefix is skipped without any `readdir`. An absent/empty `scope`
115
+ * leaves traversal and collection byte-for-byte unchanged.
116
+ *
117
+ * `platform` only selects how the exclusion comparison treats case (see
118
+ * {@link classifyScanEntry}); it defaults to the host, so every existing call is
119
+ * unchanged.
120
+ *
121
+ * Does not sort, dedupe, or emit warnings — callers handle those so their
122
+ * existing output contracts are preserved.
123
+ */
124
+ export declare function bfsCollectSupportedFiles(rootPath: string, excludePaths: readonly string[], maxDepth?: number, scope?: string[], platform?: NodeJS.Platform): Promise<DirScanResult>;
125
+ export {};
126
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/utils/scan.ts"],"names":[],"mappings":"AAyBA;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMpF;AAED,sDAAsD;AACtD,MAAM,MAAM,aAAa;AACvB,gDAAgD;AAC9C,SAAS;AACX,4EAA4E;GAC1E,UAAU;AACZ,uEAAuE;GACrE,aAAa;AACf,wEAAwE;GACtE,WAAW,CAAA;AAEf,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,CAAA;AAEhE,iEAAiE;AACjE,UAAU,cAAc;IACtB,cAAc,IAAI,OAAO,CAAA;IACzB,WAAW,IAAI,OAAO,CAAA;IACtB,MAAM,IAAI,OAAO,CAAA;CAClB;AA+BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,cAAc,EACrB,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,aAAa,CAMf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAMpC;AAED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,iFAAiF;IACjF,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,+EAA+E;IAC/E,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,8DAA8D;IAC9D,YAAY,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,QAAQ,GAAE,MAAuB,EACjC,KAAK,CAAC,EAAE,MAAM,EAAE,EAChB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAAC,aAAa,CAAC,CAgExB"}