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.
- package/LICENSE +21 -0
- package/README.de.md +416 -0
- package/README.es.md +416 -0
- package/README.fr.md +416 -0
- package/README.md +491 -0
- package/README.pt-BR.md +416 -0
- package/README.zh-CN.md +416 -0
- package/dist/bin/install-skills.d.ts +20 -0
- package/dist/bin/install-skills.d.ts.map +1 -0
- package/dist/bin/install-skills.js +195 -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 +97 -0
- package/dist/chunker/semantic-chunker.d.ts.map +1 -0
- package/dist/chunker/semantic-chunker.js +294 -0
- package/dist/chunker/semantic-chunker.js.map +1 -0
- package/dist/chunker/sentence-splitter.d.ts +28 -0
- package/dist/chunker/sentence-splitter.d.ts.map +1 -0
- package/dist/chunker/sentence-splitter.js +219 -0
- package/dist/chunker/sentence-splitter.js.map +1 -0
- package/dist/cli/common.d.ts +65 -0
- package/dist/cli/common.d.ts.map +1 -0
- package/dist/cli/common.js +138 -0
- package/dist/cli/common.js.map +1 -0
- package/dist/cli/delete.d.ts +8 -0
- package/dist/cli/delete.d.ts.map +1 -0
- package/dist/cli/delete.js +173 -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 +100 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js +363 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/list.d.ts +35 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +210 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/options.d.ts +100 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +241 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/cli/query.d.ts +24 -0
- package/dist/cli/query.d.ts.map +1 -0
- package/dist/cli/query.js +191 -0
- package/dist/cli/query.js.map +1 -0
- package/dist/cli/read-neighbors.d.ts +11 -0
- package/dist/cli/read-neighbors.d.ts.map +1 -0
- package/dist/cli/read-neighbors.js +224 -0
- package/dist/cli/read-neighbors.js.map +1 -0
- package/dist/cli/status.d.ts +8 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +80 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/sync.d.ts +8 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +244 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli-main.d.ts +12 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +63 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/embedder/index.d.ts +85 -0
- package/dist/embedder/index.d.ts.map +1 -0
- package/dist/embedder/index.js +284 -0
- package/dist/embedder/index.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 +40 -0
- package/dist/features/list.js.map +1 -0
- package/dist/features/sync.d.ts +207 -0
- package/dist/features/sync.d.ts.map +1 -0
- package/dist/features/sync.js +380 -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 +53 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/compute.d.ts +86 -0
- package/dist/ingest/compute.d.ts.map +1 -0
- package/dist/ingest/compute.js +177 -0
- package/dist/ingest/compute.js.map +1 -0
- package/dist/ingest/file.d.ts +27 -0
- package/dist/ingest/file.d.ts.map +1 -0
- package/dist/ingest/file.js +67 -0
- package/dist/ingest/file.js.map +1 -0
- package/dist/ingest/visual.d.ts +45 -0
- package/dist/ingest/visual.d.ts.map +1 -0
- package/dist/ingest/visual.js +234 -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 +328 -0
- package/dist/parser/docx-parser.js.map +1 -0
- package/dist/parser/html-parser.d.ts +18 -0
- package/dist/parser/html-parser.d.ts.map +1 -0
- package/dist/parser/html-parser.js +102 -0
- package/dist/parser/html-parser.js.map +1 -0
- package/dist/parser/index.d.ts +214 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +454 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/pdf-extract.d.ts +81 -0
- package/dist/parser/pdf-extract.d.ts.map +1 -0
- package/dist/parser/pdf-extract.js +112 -0
- package/dist/parser/pdf-extract.js.map +1 -0
- package/dist/parser/pdf-filter.d.ts +117 -0
- package/dist/parser/pdf-filter.d.ts.map +1 -0
- package/dist/parser/pdf-filter.js +528 -0
- package/dist/parser/pdf-filter.js.map +1 -0
- package/dist/parser/title-extractor.d.ts +69 -0
- package/dist/parser/title-extractor.d.ts.map +1 -0
- package/dist/parser/title-extractor.js +145 -0
- package/dist/parser/title-extractor.js.map +1 -0
- package/dist/pdf-visual/captioner.d.ts +16 -0
- package/dist/pdf-visual/captioner.d.ts.map +1 -0
- package/dist/pdf-visual/captioner.js +63 -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 +103 -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 +127 -0
- package/dist/pdf-visual/captioners/quality.js.map +1 -0
- package/dist/pdf-visual/captioners/shared.d.ts +44 -0
- package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/shared.js +104 -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 +234 -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 +45 -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 +177 -0
- package/dist/pdf-visual/renderer.js.map +1 -0
- package/dist/pdf-visual/types.d.ts +62 -0
- package/dist/pdf-visual/types.d.ts.map +1 -0
- package/dist/pdf-visual/types.js +32 -0
- package/dist/pdf-visual/types.js.map +1 -0
- package/dist/server/error-utils.d.ts +79 -0
- package/dist/server/error-utils.d.ts.map +1 -0
- package/dist/server/error-utils.js +148 -0
- package/dist/server/error-utils.js.map +1 -0
- package/dist/server/index.d.ts +258 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1104 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/list-scanner.d.ts +52 -0
- package/dist/server/list-scanner.d.ts.map +1 -0
- package/dist/server/list-scanner.js +72 -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 +216 -0
- package/dist/server/tool-input.js.map +1 -0
- package/dist/server/types.d.ts +331 -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 +46 -0
- package/dist/server-main.d.ts.map +1 -0
- package/dist/server-main.js +242 -0
- package/dist/server-main.js.map +1 -0
- package/dist/utils/base-dirs.d.ts +212 -0
- package/dist/utils/base-dirs.d.ts.map +1 -0
- package/dist/utils/base-dirs.js +422 -0
- package/dist/utils/base-dirs.js.map +1 -0
- package/dist/utils/errors.d.ts +24 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +53 -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 +47 -0
- package/dist/utils/list-sources.d.ts.map +1 -0
- package/dist/utils/list-sources.js +50 -0
- package/dist/utils/list-sources.js.map +1 -0
- package/dist/utils/raw-data-utils.d.ts +131 -0
- package/dist/utils/raw-data-utils.d.ts.map +1 -0
- package/dist/utils/raw-data-utils.js +255 -0
- package/dist/utils/raw-data-utils.js.map +1 -0
- package/dist/utils/scan.d.ts +126 -0
- package/dist/utils/scan.d.ts.map +1 -0
- package/dist/utils/scan.js +221 -0
- package/dist/utils/scan.js.map +1 -0
- package/dist/utils/scope-match.d.ts +43 -0
- package/dist/utils/scope-match.d.ts.map +1 -0
- package/dist/utils/scope-match.js +87 -0
- package/dist/utils/scope-match.js.map +1 -0
- package/dist/utils/sensitive-path.d.ts +23 -0
- package/dist/utils/sensitive-path.d.ts.map +1 -0
- package/dist/utils/sensitive-path.js +91 -0
- package/dist/utils/sensitive-path.js.map +1 -0
- package/dist/utils/sync-path-key.d.ts +20 -0
- package/dist/utils/sync-path-key.d.ts.map +1 -0
- package/dist/utils/sync-path-key.js +33 -0
- package/dist/utils/sync-path-key.js.map +1 -0
- package/dist/vectordb/index.d.ts +168 -0
- package/dist/vectordb/index.d.ts.map +1 -0
- package/dist/vectordb/index.js +619 -0
- package/dist/vectordb/index.js.map +1 -0
- package/dist/vectordb/search-filters.d.ts +39 -0
- package/dist/vectordb/search-filters.d.ts.map +1 -0
- package/dist/vectordb/search-filters.js +136 -0
- package/dist/vectordb/search-filters.js.map +1 -0
- package/dist/vectordb/types.d.ts +196 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +224 -0
- package/dist/vectordb/types.js.map +1 -0
- package/package.json +105 -0
- package/skills/mcp-local-rag/SKILL.md +308 -0
- package/skills/mcp-local-rag/references/cli-reference.md +175 -0
- package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
- package/skills/mcp-local-rag/references/query-optimization.md +57 -0
- 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"}
|