@ssmeo/mcp-local-rag 0.18.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.de.md +441 -0
- package/README.es.md +441 -0
- package/README.fr.md +441 -0
- package/README.md +530 -0
- package/README.pt-BR.md +441 -0
- package/README.zh-CN.md +441 -0
- package/dist/bin/install-skills.d.ts +19 -0
- package/dist/bin/install-skills.d.ts.map +1 -0
- package/dist/bin/install-skills.js +218 -0
- package/dist/bin/install-skills.js.map +1 -0
- package/dist/chunker/index.d.ts +24 -0
- package/dist/chunker/index.d.ts.map +1 -0
- package/dist/chunker/index.js +2 -0
- package/dist/chunker/index.js.map +1 -0
- package/dist/chunker/semantic-chunker.d.ts +96 -0
- package/dist/chunker/semantic-chunker.d.ts.map +1 -0
- package/dist/chunker/semantic-chunker.js +362 -0
- package/dist/chunker/semantic-chunker.js.map +1 -0
- package/dist/chunker/sentence-splitter.d.ts +32 -0
- package/dist/chunker/sentence-splitter.d.ts.map +1 -0
- package/dist/chunker/sentence-splitter.js +231 -0
- package/dist/chunker/sentence-splitter.js.map +1 -0
- package/dist/chunker/token-containment.d.ts +39 -0
- package/dist/chunker/token-containment.d.ts.map +1 -0
- package/dist/chunker/token-containment.js +83 -0
- package/dist/chunker/token-containment.js.map +1 -0
- package/dist/cli/common.d.ts +34 -0
- package/dist/cli/common.d.ts.map +1 -0
- package/dist/cli/common.js +121 -0
- package/dist/cli/common.js.map +1 -0
- package/dist/cli/delete.d.ts +3 -0
- package/dist/cli/delete.d.ts.map +1 -0
- package/dist/cli/delete.js +169 -0
- package/dist/cli/delete.js.map +1 -0
- package/dist/cli/file-collection.d.ts +2 -0
- package/dist/cli/file-collection.d.ts.map +1 -0
- package/dist/cli/file-collection.js +53 -0
- package/dist/cli/file-collection.js.map +1 -0
- package/dist/cli/ingest.d.ts +69 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js +323 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/list.d.ts +27 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +207 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/options.d.ts +89 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +244 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/cli/query.d.ts +17 -0
- package/dist/cli/query.d.ts.map +1 -0
- package/dist/cli/query.js +194 -0
- package/dist/cli/query.js.map +1 -0
- package/dist/cli/read-neighbors.d.ts +3 -0
- package/dist/cli/read-neighbors.d.ts.map +1 -0
- package/dist/cli/read-neighbors.js +192 -0
- package/dist/cli/read-neighbors.js.map +1 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +78 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/sync.d.ts +6 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +271 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli-main.d.ts +9 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +60 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/embedder/index.d.ts +143 -0
- package/dist/embedder/index.d.ts.map +1 -0
- package/dist/embedder/index.js +429 -0
- package/dist/embedder/index.js.map +1 -0
- package/dist/embedder/remote.d.ts +51 -0
- package/dist/embedder/remote.d.ts.map +1 -0
- package/dist/embedder/remote.js +182 -0
- package/dist/embedder/remote.js.map +1 -0
- package/dist/features/list.d.ts +37 -0
- package/dist/features/list.d.ts.map +1 -0
- package/dist/features/list.js +41 -0
- package/dist/features/list.js.map +1 -0
- package/dist/features/sync.d.ts +219 -0
- package/dist/features/sync.d.ts.map +1 -0
- package/dist/features/sync.js +461 -0
- package/dist/features/sync.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/compute.d.ts +63 -0
- package/dist/ingest/compute.d.ts.map +1 -0
- package/dist/ingest/compute.js +161 -0
- package/dist/ingest/compute.js.map +1 -0
- package/dist/ingest/file.d.ts +40 -0
- package/dist/ingest/file.d.ts.map +1 -0
- package/dist/ingest/file.js +74 -0
- package/dist/ingest/file.js.map +1 -0
- package/dist/ingest/visual.d.ts +52 -0
- package/dist/ingest/visual.d.ts.map +1 -0
- package/dist/ingest/visual.js +294 -0
- package/dist/ingest/visual.js.map +1 -0
- package/dist/parser/docx-parser.d.ts +12 -0
- package/dist/parser/docx-parser.d.ts.map +1 -0
- package/dist/parser/docx-parser.js +375 -0
- package/dist/parser/docx-parser.js.map +1 -0
- package/dist/parser/html-parser.d.ts +16 -0
- package/dist/parser/html-parser.d.ts.map +1 -0
- package/dist/parser/html-parser.js +119 -0
- package/dist/parser/html-parser.js.map +1 -0
- package/dist/parser/index.d.ts +125 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +364 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/pdf-extract.d.ts +49 -0
- package/dist/parser/pdf-extract.d.ts.map +1 -0
- package/dist/parser/pdf-extract.js +114 -0
- package/dist/parser/pdf-extract.js.map +1 -0
- package/dist/parser/pdf-filter.d.ts +91 -0
- package/dist/parser/pdf-filter.d.ts.map +1 -0
- package/dist/parser/pdf-filter.js +522 -0
- package/dist/parser/pdf-filter.js.map +1 -0
- package/dist/parser/title-extractor.d.ts +28 -0
- package/dist/parser/title-extractor.d.ts.map +1 -0
- package/dist/parser/title-extractor.js +105 -0
- package/dist/parser/title-extractor.js.map +1 -0
- package/dist/pdf-visual/captioner.d.ts +11 -0
- package/dist/pdf-visual/captioner.d.ts.map +1 -0
- package/dist/pdf-visual/captioner.js +48 -0
- package/dist/pdf-visual/captioner.js.map +1 -0
- package/dist/pdf-visual/captioners/fast.d.ts +7 -0
- package/dist/pdf-visual/captioners/fast.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/fast.js +108 -0
- package/dist/pdf-visual/captioners/fast.js.map +1 -0
- package/dist/pdf-visual/captioners/quality.d.ts +7 -0
- package/dist/pdf-visual/captioners/quality.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/quality.js +101 -0
- package/dist/pdf-visual/captioners/quality.js.map +1 -0
- package/dist/pdf-visual/captioners/shared.d.ts +81 -0
- package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/shared.js +156 -0
- package/dist/pdf-visual/captioners/shared.js.map +1 -0
- package/dist/pdf-visual/detector.d.ts +9 -0
- package/dist/pdf-visual/detector.d.ts.map +1 -0
- package/dist/pdf-visual/detector.js +269 -0
- package/dist/pdf-visual/detector.js.map +1 -0
- package/dist/pdf-visual/index.d.ts +13 -0
- package/dist/pdf-visual/index.d.ts.map +1 -0
- package/dist/pdf-visual/index.js +53 -0
- package/dist/pdf-visual/index.js.map +1 -0
- package/dist/pdf-visual/renderer.d.ts +9 -0
- package/dist/pdf-visual/renderer.d.ts.map +1 -0
- package/dist/pdf-visual/renderer.js +186 -0
- package/dist/pdf-visual/renderer.js.map +1 -0
- package/dist/pdf-visual/types.d.ts +53 -0
- package/dist/pdf-visual/types.d.ts.map +1 -0
- package/dist/pdf-visual/types.js +17 -0
- package/dist/pdf-visual/types.js.map +1 -0
- package/dist/server/error-utils.d.ts +63 -0
- package/dist/server/error-utils.d.ts.map +1 -0
- package/dist/server/error-utils.js +124 -0
- package/dist/server/error-utils.js.map +1 -0
- package/dist/server/index.d.ts +216 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1068 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/list-scanner.d.ts +30 -0
- package/dist/server/list-scanner.d.ts.map +1 -0
- package/dist/server/list-scanner.js +50 -0
- package/dist/server/list-scanner.js.map +1 -0
- package/dist/server/tool-definitions.d.ts +8 -0
- package/dist/server/tool-definitions.d.ts.map +1 -0
- package/dist/server/tool-definitions.js +181 -0
- package/dist/server/tool-definitions.js.map +1 -0
- package/dist/server/tool-input.d.ts +37 -0
- package/dist/server/tool-input.d.ts.map +1 -0
- package/dist/server/tool-input.js +211 -0
- package/dist/server/tool-input.js.map +1 -0
- package/dist/server/types.d.ts +307 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +3 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server-main.d.ts +40 -0
- package/dist/server-main.d.ts.map +1 -0
- package/dist/server-main.js +254 -0
- package/dist/server-main.js.map +1 -0
- package/dist/utils/base-dirs.d.ts +145 -0
- package/dist/utils/base-dirs.d.ts.map +1 -0
- package/dist/utils/base-dirs.js +344 -0
- package/dist/utils/base-dirs.js.map +1 -0
- package/dist/utils/errors.d.ts +32 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +61 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/limits.d.ts +26 -0
- package/dist/utils/limits.d.ts.map +1 -0
- package/dist/utils/limits.js +28 -0
- package/dist/utils/limits.js.map +1 -0
- package/dist/utils/list-sources.d.ts +38 -0
- package/dist/utils/list-sources.d.ts.map +1 -0
- package/dist/utils/list-sources.js +40 -0
- package/dist/utils/list-sources.js.map +1 -0
- package/dist/utils/raw-data-utils.d.ts +76 -0
- package/dist/utils/raw-data-utils.d.ts.map +1 -0
- package/dist/utils/raw-data-utils.js +202 -0
- package/dist/utils/raw-data-utils.js.map +1 -0
- package/dist/utils/scan.d.ts +114 -0
- package/dist/utils/scan.d.ts.map +1 -0
- package/dist/utils/scan.js +209 -0
- package/dist/utils/scan.js.map +1 -0
- package/dist/utils/scope-match.d.ts +38 -0
- package/dist/utils/scope-match.d.ts.map +1 -0
- package/dist/utils/scope-match.js +86 -0
- package/dist/utils/scope-match.js.map +1 -0
- package/dist/utils/sensitive-path.d.ts +9 -0
- package/dist/utils/sensitive-path.d.ts.map +1 -0
- package/dist/utils/sensitive-path.js +78 -0
- package/dist/utils/sensitive-path.js.map +1 -0
- package/dist/utils/sync-path-key.d.ts +14 -0
- package/dist/utils/sync-path-key.d.ts.map +1 -0
- package/dist/utils/sync-path-key.js +27 -0
- package/dist/utils/sync-path-key.js.map +1 -0
- package/dist/utils/type-guards.d.ts +18 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +34 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/dist/utils/visual-profile.d.ts +10 -0
- package/dist/utils/visual-profile.d.ts.map +1 -0
- package/dist/utils/visual-profile.js +15 -0
- package/dist/utils/visual-profile.js.map +1 -0
- package/dist/vectordb/index.d.ts +132 -0
- package/dist/vectordb/index.d.ts.map +1 -0
- package/dist/vectordb/index.js +617 -0
- package/dist/vectordb/index.js.map +1 -0
- package/dist/vectordb/search-filters.d.ts +15 -0
- package/dist/vectordb/search-filters.d.ts.map +1 -0
- package/dist/vectordb/search-filters.js +129 -0
- package/dist/vectordb/search-filters.js.map +1 -0
- package/dist/vectordb/types.d.ts +194 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +237 -0
- package/dist/vectordb/types.js.map +1 -0
- package/package.json +108 -0
- package/skills/mcp-local-rag/SKILL.md +234 -0
- package/skills/mcp-local-rag/references/cli-reference.md +190 -0
- package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { Document as MupdfDocument } from 'mupdf';
|
|
2
|
+
import { type AtomicTextRange } from '../chunker/index.js';
|
|
3
|
+
import { AppError } from '../utils/errors.js';
|
|
4
|
+
import type { EmbedderInterface, FilteredTextFragment } from './pdf-filter.js';
|
|
5
|
+
/**
|
|
6
|
+
* File extensions supported by the parser module (parseFile + parsePdf).
|
|
7
|
+
* Exported so other modules (e.g. list_files) stay in sync automatically
|
|
8
|
+
* when new formats are added here.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SUPPORTED_EXTENSIONS: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Result from parsing a document, containing both content and extracted title.
|
|
13
|
+
* Title is display-only metadata (NOT used for search scoring).
|
|
14
|
+
*/
|
|
15
|
+
export interface ParseResult {
|
|
16
|
+
content: string;
|
|
17
|
+
title: string;
|
|
18
|
+
atomicRanges?: readonly AtomicTextRange[];
|
|
19
|
+
imageAnchors?: readonly ParsedImageAnchor[];
|
|
20
|
+
}
|
|
21
|
+
export interface ParsedImageAnchor {
|
|
22
|
+
offset: number;
|
|
23
|
+
imageIndex: number;
|
|
24
|
+
mimeType: 'image/png' | 'image/jpeg';
|
|
25
|
+
bytes: Uint8Array;
|
|
26
|
+
}
|
|
27
|
+
export interface ParseFileOptions {
|
|
28
|
+
images?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* DocumentParser configuration. Exactly one of `baseDir` (legacy single root)
|
|
32
|
+
* or `baseDirs` must be supplied; the constructor rejects both, so a
|
|
33
|
+
* misconfiguration cannot silently pick one.
|
|
34
|
+
*/
|
|
35
|
+
export type ParserConfig = {
|
|
36
|
+
/** Security: single allowed base directory (legacy shape). */
|
|
37
|
+
baseDir: string;
|
|
38
|
+
baseDirs?: undefined;
|
|
39
|
+
/** Maximum file size (100MB). */
|
|
40
|
+
maxFileSize: number;
|
|
41
|
+
} | {
|
|
42
|
+
/** Security: one or more allowed base directories (multi-root shape). */
|
|
43
|
+
baseDirs: readonly string[];
|
|
44
|
+
baseDir?: undefined;
|
|
45
|
+
/** Maximum file size (100MB). */
|
|
46
|
+
maxFileSize: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Validation error (equivalent to 400)
|
|
50
|
+
*/
|
|
51
|
+
export declare class ValidationError extends AppError {
|
|
52
|
+
constructor(message: string, options?: {
|
|
53
|
+
cause?: Error;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* File operation error (equivalent to 500)
|
|
58
|
+
*/
|
|
59
|
+
export declare class FileOperationError extends AppError {
|
|
60
|
+
constructor(message: string, options?: {
|
|
61
|
+
cause?: Error;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** Path and size validation plus PDF/DOCX/TXT/MD parsing. */
|
|
65
|
+
export declare class DocumentParser {
|
|
66
|
+
private readonly config;
|
|
67
|
+
/** Raw allowed roots in input order (pre-realpath). Always non-empty. */
|
|
68
|
+
private readonly rawBaseDirs;
|
|
69
|
+
/**
|
|
70
|
+
* Realpath-normalized allowed roots, each with a trailing separator so the
|
|
71
|
+
* `startsWith` check cannot match a sibling (`/foo/bar/` vs `/foo/barista/`).
|
|
72
|
+
* Cached for the process lifetime.
|
|
73
|
+
*/
|
|
74
|
+
private resolvedBaseDirs;
|
|
75
|
+
constructor(config: ParserConfig);
|
|
76
|
+
/**
|
|
77
|
+
* THE place realpath is used: following symlinks here is what makes prefix
|
|
78
|
+
* containment unforgeable. Everything else stores and looks up resolve()
|
|
79
|
+
* paths — see {@link BaseDirsConfig}.
|
|
80
|
+
*
|
|
81
|
+
* A file is accepted iff its realpath — or, for a not-yet-existing
|
|
82
|
+
* non-symlink, its resolve()d path — sits under any allowed root. A broken
|
|
83
|
+
* symlink is rejected outright.
|
|
84
|
+
*/
|
|
85
|
+
validateFilePath(filePath: string): Promise<void>;
|
|
86
|
+
/** @throws ValidationError when the file exceeds the configured size limit. */
|
|
87
|
+
validateFileSize(filePath: string): void;
|
|
88
|
+
/** Parse a file, detecting the format from its extension. */
|
|
89
|
+
parseFile(filePath: string, options?: ParseFileOptions): Promise<ParseResult>;
|
|
90
|
+
/**
|
|
91
|
+
* PDF parsing. Headers and footers are detected semantically by embedding
|
|
92
|
+
* similarity across pages, not by position alone, and the title comes from
|
|
93
|
+
* PDF metadata with a first-page largest-font fallback.
|
|
94
|
+
*/
|
|
95
|
+
parsePdf(filePath: string, embedder: EmbedderInterface): Promise<ParseResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Per-page PDF parsing for the visual path. Adds `preserve-images` so mupdf
|
|
98
|
+
* emits the image blocks the visual detector needs, and returns the open
|
|
99
|
+
* `Document` so the renderer can work on the same handle.
|
|
100
|
+
*
|
|
101
|
+
* Disposal is asymmetric: on success the CALLER owns `doc` and must
|
|
102
|
+
* `finally { doc.destroy() }`; on throw `doc` is already destroyed here, so
|
|
103
|
+
* the caller must NOT destroy it.
|
|
104
|
+
*/
|
|
105
|
+
parsePdfPages(filePath: string, embedder: EmbedderInterface): Promise<{
|
|
106
|
+
doc: MupdfDocument;
|
|
107
|
+
title: string;
|
|
108
|
+
pages: Array<{
|
|
109
|
+
pageNum: number;
|
|
110
|
+
text: string;
|
|
111
|
+
textFragments: FilteredTextFragment[];
|
|
112
|
+
stextJson: unknown;
|
|
113
|
+
}>;
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* DOCX parsing. One Mammoth HTML conversion serves both title and body, so
|
|
117
|
+
* the document is not converted twice.
|
|
118
|
+
*/
|
|
119
|
+
private parseDocx;
|
|
120
|
+
/** TXT parsing. */
|
|
121
|
+
private parseTxt;
|
|
122
|
+
/** MD parsing. */
|
|
123
|
+
private parseMd;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
// DocumentParser implementation with PDF/DOCX/TXT/MD support
|
|
2
|
+
import { statSync } from 'node:fs';
|
|
3
|
+
import { lstat, readFile, realpath } from 'node:fs/promises';
|
|
4
|
+
import { basename, extname, isAbsolute, resolve } from 'node:path';
|
|
5
|
+
import { JSDOM } from 'jsdom';
|
|
6
|
+
import mammoth from 'mammoth';
|
|
7
|
+
import { SemanticChunker } from '../chunker/index.js';
|
|
8
|
+
import { withTrailingSeparator } from '../utils/base-dirs.js';
|
|
9
|
+
import { AppError, isAppError, toError } from '../utils/errors.js';
|
|
10
|
+
import { errorCode } from '../utils/type-guards.js';
|
|
11
|
+
import { convertDocxDocumentToText, extractDocxCoreTitle } from './docx-parser.js';
|
|
12
|
+
import { extractPdfPages } from './pdf-extract.js';
|
|
13
|
+
import { extractDocxTitle, extractMarkdownTitle, extractPdfTitle, extractTxtTitle, } from './title-extractor.js';
|
|
14
|
+
// ============================================
|
|
15
|
+
// Supported Extensions
|
|
16
|
+
// ============================================
|
|
17
|
+
/**
|
|
18
|
+
* File extensions supported by the parser module (parseFile + parsePdf).
|
|
19
|
+
* Exported so other modules (e.g. list_files) stay in sync automatically
|
|
20
|
+
* when new formats are added here.
|
|
21
|
+
*/
|
|
22
|
+
export const SUPPORTED_EXTENSIONS = new Set(['.pdf', '.docx', '.txt', '.md']);
|
|
23
|
+
async function resolvePdfTitle(filePath, pages, hints, embedder) {
|
|
24
|
+
const { metadataTitle, page1FontHint } = hints;
|
|
25
|
+
const fileName = basename(filePath);
|
|
26
|
+
let firstPageChunkText;
|
|
27
|
+
try {
|
|
28
|
+
const filteredPage1 = pages[0]?.text;
|
|
29
|
+
if (filteredPage1 && filteredPage1.trim().length > 0) {
|
|
30
|
+
const page1Chunks = await new SemanticChunker().chunkText(filteredPage1, embedder);
|
|
31
|
+
firstPageChunkText = page1Chunks[0]?.text;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (titleError) {
|
|
35
|
+
if (isAppError(titleError)) {
|
|
36
|
+
throw titleError;
|
|
37
|
+
}
|
|
38
|
+
console.error(`Title extraction failed, falling back to filename: ${titleError}`);
|
|
39
|
+
}
|
|
40
|
+
return extractPdfTitle(metadataTitle, firstPageChunkText, fileName, page1FontHint).title;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validation error (equivalent to 400)
|
|
44
|
+
*/
|
|
45
|
+
export class ValidationError extends AppError {
|
|
46
|
+
constructor(message, options) {
|
|
47
|
+
super(message, 'parser', 'validation', options);
|
|
48
|
+
this.name = 'ValidationError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* File operation error (equivalent to 500)
|
|
53
|
+
*/
|
|
54
|
+
export class FileOperationError extends AppError {
|
|
55
|
+
constructor(message, options) {
|
|
56
|
+
super(message, 'parser', 'io', options);
|
|
57
|
+
this.name = 'FileOperationError';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ============================================
|
|
61
|
+
// DocumentParser Class
|
|
62
|
+
// ============================================
|
|
63
|
+
/** Path and size validation plus PDF/DOCX/TXT/MD parsing. */
|
|
64
|
+
export class DocumentParser {
|
|
65
|
+
config;
|
|
66
|
+
/** Raw allowed roots in input order (pre-realpath). Always non-empty. */
|
|
67
|
+
rawBaseDirs;
|
|
68
|
+
/**
|
|
69
|
+
* Realpath-normalized allowed roots, each with a trailing separator so the
|
|
70
|
+
* `startsWith` check cannot match a sibling (`/foo/bar/` vs `/foo/barista/`).
|
|
71
|
+
* Cached for the process lifetime.
|
|
72
|
+
*/
|
|
73
|
+
resolvedBaseDirs = null;
|
|
74
|
+
constructor(config) {
|
|
75
|
+
this.config = config;
|
|
76
|
+
// `baseDirs` wins so a future relaxation of the type cannot fall back to
|
|
77
|
+
// the legacy field. An empty list is accepted only so the parser is
|
|
78
|
+
// constructible in the server's degraded mode; `validateFilePath` then
|
|
79
|
+
// fails closed, accepting nothing.
|
|
80
|
+
if (config.baseDirs !== undefined) {
|
|
81
|
+
this.rawBaseDirs = config.baseDirs;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.rawBaseDirs = [config.baseDir];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* THE place realpath is used: following symlinks here is what makes prefix
|
|
89
|
+
* containment unforgeable. Everything else stores and looks up resolve()
|
|
90
|
+
* paths — see {@link BaseDirsConfig}.
|
|
91
|
+
*
|
|
92
|
+
* A file is accepted iff its realpath — or, for a not-yet-existing
|
|
93
|
+
* non-symlink, its resolve()d path — sits under any allowed root. A broken
|
|
94
|
+
* symlink is rejected outright.
|
|
95
|
+
*/
|
|
96
|
+
async validateFilePath(filePath) {
|
|
97
|
+
// Fail closed in degraded mode: an empty allow-list must reject every
|
|
98
|
+
// path, not run a prefix check against no roots. `assertConfigOk` should
|
|
99
|
+
// fire first; this covers paths that bypass it.
|
|
100
|
+
if (this.rawBaseDirs.length === 0) {
|
|
101
|
+
throw new ValidationError('No configured base directory: file access is disabled. Resolve the BASE_DIR / BASE_DIRS configuration error reported by the `status` tool before retrying.');
|
|
102
|
+
}
|
|
103
|
+
// Check if path is absolute (fast-fail without syscall)
|
|
104
|
+
if (!isAbsolute(filePath)) {
|
|
105
|
+
throw new ValidationError(`File path must be absolute path (received: ${filePath}). Please provide an absolute path within a configured base directory (BASE_DIR/BASE_DIRS/--base-dir).`);
|
|
106
|
+
}
|
|
107
|
+
// Lazily resolve and cache the real path of each allowed root (follows
|
|
108
|
+
// symlinks). Each entry gets a trailing separator so subsequent
|
|
109
|
+
// `startsWith` checks are sibling-prefix safe.
|
|
110
|
+
if (!this.resolvedBaseDirs) {
|
|
111
|
+
const resolvedList = [];
|
|
112
|
+
for (const raw of this.rawBaseDirs) {
|
|
113
|
+
const resolved = await realpath(resolve(raw));
|
|
114
|
+
resolvedList.push(withTrailingSeparator(resolved));
|
|
115
|
+
}
|
|
116
|
+
this.resolvedBaseDirs = resolvedList;
|
|
117
|
+
}
|
|
118
|
+
// Resolve the real path of the file (follows symlinks)
|
|
119
|
+
let resolvedPath;
|
|
120
|
+
try {
|
|
121
|
+
resolvedPath = await realpath(filePath);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
// realpath fails if path doesn't exist on filesystem.
|
|
125
|
+
// Distinguish broken symlinks from genuinely non-existent paths:
|
|
126
|
+
// - Broken symlink: lstat succeeds (symlink entry exists) -> reject
|
|
127
|
+
// - Non-existent path: lstat fails -> fall back to resolve() for validation
|
|
128
|
+
const isSymlink = await lstat(filePath)
|
|
129
|
+
.then((stats) => stats.isSymbolicLink())
|
|
130
|
+
.catch(() => false);
|
|
131
|
+
if (isSymlink) {
|
|
132
|
+
throw new ValidationError(`Cannot resolve file path: ${filePath}. The file may not exist or is a broken symlink.`, { cause: toError(error) });
|
|
133
|
+
}
|
|
134
|
+
// File doesn't exist at all - fall back to resolve() for path validation.
|
|
135
|
+
// Note: resolve() is string-based and cannot detect symlinked parent directories.
|
|
136
|
+
// This is acceptable because non-existent files will fail at subsequent readFile/statSync.
|
|
137
|
+
resolvedPath = resolve(filePath);
|
|
138
|
+
}
|
|
139
|
+
// Check if resolved path is within any allowed root.
|
|
140
|
+
const allowed = this.resolvedBaseDirs.some((root) => resolvedPath.startsWith(root));
|
|
141
|
+
if (!allowed) {
|
|
142
|
+
const rootsDisplay = this.resolvedBaseDirs.length === 1
|
|
143
|
+
? this.resolvedBaseDirs[0]
|
|
144
|
+
: this.resolvedBaseDirs.join(', ');
|
|
145
|
+
throw new ValidationError(`File path must be within a configured base directory (BASE_DIR/BASE_DIRS/--base-dir). Allowed roots: ${rootsDisplay}. Received path outside all configured roots: ${filePath}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** @throws ValidationError when the file exceeds the configured size limit. */
|
|
149
|
+
validateFileSize(filePath) {
|
|
150
|
+
try {
|
|
151
|
+
const stats = statSync(filePath);
|
|
152
|
+
if (stats.size > this.config.maxFileSize) {
|
|
153
|
+
throw new ValidationError(`File size exceeds limit: ${stats.size} > ${this.config.maxFileSize}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error instanceof ValidationError) {
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
// Missing file is an input error, not an I/O fault.
|
|
161
|
+
if (errorCode(error) === 'ENOENT') {
|
|
162
|
+
throw new ValidationError(`File not found: ${filePath}`);
|
|
163
|
+
}
|
|
164
|
+
throw new FileOperationError(`Failed to check file size: ${filePath}`, {
|
|
165
|
+
cause: toError(error),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/** Parse a file, detecting the format from its extension. */
|
|
170
|
+
async parseFile(filePath, options = {}) {
|
|
171
|
+
// Validation
|
|
172
|
+
await this.validateFilePath(filePath);
|
|
173
|
+
this.validateFileSize(filePath);
|
|
174
|
+
// Format detection (PDF uses parsePdf directly)
|
|
175
|
+
const ext = extname(filePath).toLowerCase();
|
|
176
|
+
switch (ext) {
|
|
177
|
+
case '.docx':
|
|
178
|
+
return await this.parseDocx(filePath, options.images === true);
|
|
179
|
+
case '.txt':
|
|
180
|
+
return await this.parseTxt(filePath);
|
|
181
|
+
case '.md':
|
|
182
|
+
return await this.parseMd(filePath);
|
|
183
|
+
default:
|
|
184
|
+
throw new ValidationError(`Unsupported file format: ${ext}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* PDF parsing. Headers and footers are detected semantically by embedding
|
|
189
|
+
* similarity across pages, not by position alone, and the title comes from
|
|
190
|
+
* PDF metadata with a first-page largest-font fallback.
|
|
191
|
+
*/
|
|
192
|
+
async parsePdf(filePath, embedder) {
|
|
193
|
+
// Validation
|
|
194
|
+
await this.validateFilePath(filePath);
|
|
195
|
+
this.validateFileSize(filePath);
|
|
196
|
+
// Hold `doc` outside the try so the `finally` block can dispose it after
|
|
197
|
+
// either a successful return or an error from `extractPdfPages` / the
|
|
198
|
+
// post-processing steps. `doc` stays `undefined` if `openDocument` itself
|
|
199
|
+
// throws — in that case there is no handle to destroy.
|
|
200
|
+
let doc;
|
|
201
|
+
try {
|
|
202
|
+
const buffer = await readFile(filePath);
|
|
203
|
+
const mupdf = await import('mupdf');
|
|
204
|
+
doc = mupdf.Document.openDocument(buffer, 'application/pdf');
|
|
205
|
+
const { pages, metadataTitle, page1FontHint } = await extractPdfPages(doc, embedder, 'preserve-whitespace');
|
|
206
|
+
const text = pages
|
|
207
|
+
.map((p) => p.text)
|
|
208
|
+
.filter((t) => t.length > 0)
|
|
209
|
+
.join('\n\n');
|
|
210
|
+
const title = await resolvePdfTitle(filePath, pages, { metadataTitle, page1FontHint }, embedder);
|
|
211
|
+
console.error(`Parsed PDF: ${filePath} (${text.length} characters, ${pages.length} pages)`);
|
|
212
|
+
return { content: text, title };
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
// A foreign domain error (an `EmbeddingError` raised while the parser
|
|
216
|
+
// used the embedder) keeps its identity rather than being relabelled a
|
|
217
|
+
// PDF failure. Only a genuine non-`AppError` wraps as `FileOperationError`.
|
|
218
|
+
if (isAppError(error)) {
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
throw new FileOperationError(`Failed to parse PDF: ${filePath}`, { cause: toError(error) });
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
// Release the native WASM handle exactly once per invocation, on both
|
|
225
|
+
// success and error paths.
|
|
226
|
+
doc?.destroy();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Per-page PDF parsing for the visual path. Adds `preserve-images` so mupdf
|
|
231
|
+
* emits the image blocks the visual detector needs, and returns the open
|
|
232
|
+
* `Document` so the renderer can work on the same handle.
|
|
233
|
+
*
|
|
234
|
+
* Disposal is asymmetric: on success the CALLER owns `doc` and must
|
|
235
|
+
* `finally { doc.destroy() }`; on throw `doc` is already destroyed here, so
|
|
236
|
+
* the caller must NOT destroy it.
|
|
237
|
+
*/
|
|
238
|
+
async parsePdfPages(filePath, embedder) {
|
|
239
|
+
// Validation (mirrors parsePdf's entry-point contract so the visual path
|
|
240
|
+
// does not bypass BASE_DIR / size checks).
|
|
241
|
+
await this.validateFilePath(filePath);
|
|
242
|
+
this.validateFileSize(filePath);
|
|
243
|
+
// Open the doc and run per-page extraction. Success-path disposal of
|
|
244
|
+
// `doc` stays with the caller.
|
|
245
|
+
// For the error-path window between `openDocument` and the return below,
|
|
246
|
+
// destroy `doc` here before re-throwing so a failure in `extractPdfPages`
|
|
247
|
+
// (or any future pre-return step) does not leak the mupdf WASM handle.
|
|
248
|
+
let doc;
|
|
249
|
+
try {
|
|
250
|
+
const buffer = await readFile(filePath);
|
|
251
|
+
const mupdf = await import('mupdf');
|
|
252
|
+
doc = mupdf.Document.openDocument(buffer, 'application/pdf');
|
|
253
|
+
const extracted = await extractPdfPages(doc, embedder, 'preserve-whitespace,preserve-images');
|
|
254
|
+
const { pages: helperPages, metadataTitle, page1FontHint } = extracted;
|
|
255
|
+
const pages = helperPages.map((page) => ({
|
|
256
|
+
pageNum: page.pageNum,
|
|
257
|
+
text: page.text,
|
|
258
|
+
textFragments: page.textFragments,
|
|
259
|
+
stextJson: page.stextJson,
|
|
260
|
+
}));
|
|
261
|
+
const title = await resolvePdfTitle(filePath, helperPages, { metadataTitle, page1FontHint }, embedder);
|
|
262
|
+
console.error(`Parsed PDF pages: ${filePath} (${pages.length} pages; caller owns doc disposal)`);
|
|
263
|
+
return { doc, title, pages };
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
// `doc` is undefined when `openDocument` itself threw — nothing to free.
|
|
267
|
+
// When it is defined, dispose before re-throwing (on BOTH the foreign and
|
|
268
|
+
// the genuine error paths) so the caller never receives the handle and
|
|
269
|
+
// cannot be expected to clean it up.
|
|
270
|
+
doc?.destroy();
|
|
271
|
+
// A foreign domain error (e.g. `EmbeddingError`) keeps its identity —
|
|
272
|
+
// rethrow it unchanged. Only a genuine non-`AppError` IO/mupdf failure
|
|
273
|
+
// wraps as `FileOperationError` with its `.cause` set.
|
|
274
|
+
if (isAppError(error)) {
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
throw new FileOperationError(`Failed to parse PDF pages: ${filePath}`, {
|
|
278
|
+
cause: toError(error),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* DOCX parsing. One Mammoth HTML conversion serves both title and body, so
|
|
284
|
+
* the document is not converted twice.
|
|
285
|
+
*/
|
|
286
|
+
async parseDocx(filePath, includeImages) {
|
|
287
|
+
try {
|
|
288
|
+
const buffer = await readFile(filePath);
|
|
289
|
+
const capturedImages = new Map();
|
|
290
|
+
let nextImageIndex = 0;
|
|
291
|
+
let skippedImageCount = 0;
|
|
292
|
+
const htmlResult = includeImages
|
|
293
|
+
? await mammoth.convertToHtml({ buffer }, {
|
|
294
|
+
convertImage: mammoth.images.imgElement(async (image) => {
|
|
295
|
+
const imageIndex = nextImageIndex++;
|
|
296
|
+
if (image.contentType !== 'image/png' && image.contentType !== 'image/jpeg') {
|
|
297
|
+
skippedImageCount += 1;
|
|
298
|
+
return { src: `data:${image.contentType};base64,` };
|
|
299
|
+
}
|
|
300
|
+
const bytes = await image.readAsBuffer().catch(() => null);
|
|
301
|
+
if (bytes === null) {
|
|
302
|
+
skippedImageCount += 1;
|
|
303
|
+
return { src: `data:${image.contentType};base64,` };
|
|
304
|
+
}
|
|
305
|
+
capturedImages.set(imageIndex, { mimeType: image.contentType, bytes });
|
|
306
|
+
return {
|
|
307
|
+
src: `data:${image.contentType};base64,`,
|
|
308
|
+
'data-rag-image-index': String(imageIndex),
|
|
309
|
+
};
|
|
310
|
+
}),
|
|
311
|
+
})
|
|
312
|
+
: await mammoth.convertToHtml({ buffer });
|
|
313
|
+
const htmlDocument = new JSDOM(htmlResult.value).window.document;
|
|
314
|
+
const coreTitle = await extractDocxCoreTitle(buffer);
|
|
315
|
+
const body = convertDocxDocumentToText(htmlDocument);
|
|
316
|
+
const fileName = basename(filePath);
|
|
317
|
+
const titleResult = extractDocxTitle(htmlDocument, fileName, coreTitle);
|
|
318
|
+
console.error(`Parsed DOCX: ${filePath} (${body.content.length} characters)`);
|
|
319
|
+
if (skippedImageCount > 0) {
|
|
320
|
+
console.warn(`Skipped ${skippedImageCount} unsupported or unreadable DOCX image(s) in ${filePath}; only embedded PNG and JPEG are supported`);
|
|
321
|
+
}
|
|
322
|
+
const imageAnchors = (body.imageAnchors ?? []).flatMap((anchor) => {
|
|
323
|
+
const captured = capturedImages.get(anchor.imageIndex);
|
|
324
|
+
return captured ? [{ ...anchor, ...captured }] : [];
|
|
325
|
+
});
|
|
326
|
+
return {
|
|
327
|
+
content: body.content,
|
|
328
|
+
title: titleResult.title,
|
|
329
|
+
...(body.atomicRanges.length === 0 ? {} : { atomicRanges: body.atomicRanges }),
|
|
330
|
+
...(imageAnchors.length === 0 ? {} : { imageAnchors }),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
throw new FileOperationError(`Failed to parse DOCX: ${filePath}`, { cause: toError(error) });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/** TXT parsing. */
|
|
338
|
+
async parseTxt(filePath) {
|
|
339
|
+
try {
|
|
340
|
+
const text = await readFile(filePath, 'utf-8');
|
|
341
|
+
const fileName = basename(filePath);
|
|
342
|
+
const titleResult = extractTxtTitle(text, fileName);
|
|
343
|
+
console.error(`Parsed TXT: ${filePath} (${text.length} characters)`);
|
|
344
|
+
return { content: text, title: titleResult.title };
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
throw new FileOperationError(`Failed to parse TXT: ${filePath}`, { cause: toError(error) });
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** MD parsing. */
|
|
351
|
+
async parseMd(filePath) {
|
|
352
|
+
try {
|
|
353
|
+
const text = await readFile(filePath, 'utf-8');
|
|
354
|
+
const fileName = basename(filePath);
|
|
355
|
+
const titleResult = extractMarkdownTitle(text, fileName);
|
|
356
|
+
console.error(`Parsed MD: ${filePath} (${text.length} characters)`);
|
|
357
|
+
return { content: text, title: titleResult.title };
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
throw new FileOperationError(`Failed to parse MD: ${filePath}`, { cause: toError(error) });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Document as MupdfDocument } from 'mupdf';
|
|
2
|
+
import { type EmbedderInterface, type FilteredTextFragment } from './pdf-filter.js';
|
|
3
|
+
interface StextBbox {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
}
|
|
9
|
+
/** The part of mupdf's structured-text JSON this module reads. */
|
|
10
|
+
interface StextJson {
|
|
11
|
+
blocks: Array<{
|
|
12
|
+
type: string;
|
|
13
|
+
/** Present on image blocks; the visual detector reads it to locate rasters. */
|
|
14
|
+
bbox?: StextBbox;
|
|
15
|
+
lines?: Array<{
|
|
16
|
+
text: string;
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
bbox?: StextBbox;
|
|
20
|
+
font: {
|
|
21
|
+
size: number;
|
|
22
|
+
name?: string;
|
|
23
|
+
weight?: string;
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `text` is post-header/footer-filtering; `stextJson` is the raw mupdf JSON,
|
|
30
|
+
* kept for the downstream visual detector.
|
|
31
|
+
*/
|
|
32
|
+
interface ExtractedPage {
|
|
33
|
+
pageNum: number;
|
|
34
|
+
text: string;
|
|
35
|
+
textFragments: FilteredTextFragment[];
|
|
36
|
+
stextJson: StextJson;
|
|
37
|
+
}
|
|
38
|
+
/** Result returned by `extractPdfPages`. */
|
|
39
|
+
interface ExtractedPdf {
|
|
40
|
+
pages: ExtractedPage[];
|
|
41
|
+
metadataTitle: string | undefined;
|
|
42
|
+
page1FontHint: {
|
|
43
|
+
text: string;
|
|
44
|
+
fontSize: number;
|
|
45
|
+
} | undefined;
|
|
46
|
+
}
|
|
47
|
+
export declare function extractPdfPages(doc: MupdfDocument, embedder: EmbedderInterface, stextOptions: string): Promise<ExtractedPdf>;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=pdf-extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-extract.d.ts","sourceRoot":"","sources":["../../src/parser/pdf-extract.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,IAAI,aAAa,EAAqB,MAAM,OAAO,CAAA;AAEzE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAG1B,MAAM,iBAAiB,CAAA;AAExB,UAAU,SAAS;IACjB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,kEAAkE;AAClE,UAAU,SAAS;IACjB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,+EAA+E;QAC/E,IAAI,CAAC,EAAE,SAAS,CAAA;QAChB,KAAK,CAAC,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,CAAC,EAAE,MAAM,CAAA;YACT,CAAC,EAAE,MAAM,CAAA;YACT,IAAI,CAAC,EAAE,SAAS,CAAA;YAChB,IAAI,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAAC,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE,CAAA;SACvD,CAAC,CAAA;KACH,CAAC,CAAA;CACH;AAED;;;GAGG;AACH,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,oBAAoB,EAAE,CAAA;IACrC,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,4CAA4C;AAC5C,UAAU,YAAY;IACpB,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,aAAa,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;CAC9D;AAwFD,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,YAAY,CAAC,CAgCvB"}
|