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