@bitbonsai/mcpvault 0.11.4 → 0.12.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.md +2 -1
- package/dist/src/createServer.d.ts.map +1 -1
- package/dist/src/createServer.js +5 -1
- package/dist/src/filesystem.d.ts +10 -0
- package/dist/src/filesystem.d.ts.map +1 -1
- package/dist/src/filesystem.js +28 -9
- package/dist/src/pathfilter.d.ts +1 -0
- package/dist/src/pathfilter.d.ts.map +1 -1
- package/dist/src/pathfilter.js +20 -0
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +21 -4
- package/dist/src/types.d.ts +4 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mauricio Wolff
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ A universal AI bridge for Obsidian vaults using the Model Context Protocol (MCP)
|
|
|
27
27
|
|
|
28
28
|
## Universal Compatibility
|
|
29
29
|
|
|
30
|
-
Works with any MCP-compatible AI assistant including Claude Desktop, Claude Code, ChatGPT Desktop (Enterprise+), OpenCode, Gemini CLI, OpenAI Codex, IntelliJ IDEA 2025.1+, Cursor IDE, Windsurf IDE, and future AI platforms that adopt the MCP standard.
|
|
30
|
+
Works with any MCP-compatible AI assistant including Claude Desktop, Claude Code, ChatGPT Desktop (Enterprise+), OpenCode, Gemini CLI, OpenAI Codex, IntelliJ IDEA 2025.1+, Cursor IDE, Windsurf IDE, Ontheia, and future AI platforms that adopt the MCP standard.
|
|
31
31
|
|
|
32
32
|
https://github.com/user-attachments/assets/657ac4c6-1cd2-4cc3-829f-fd095a32f71c
|
|
33
33
|
|
|
@@ -334,6 +334,7 @@ npx @bitbonsai/mcpvault@latest /path/to/your/vault
|
|
|
334
334
|
- **IntelliJ IDEA 2025.1+** - Native MCP client support
|
|
335
335
|
- **Cursor IDE** - Built-in MCP compatibility
|
|
336
336
|
- **Windsurf IDE** - Full MCP integration
|
|
337
|
+
- **[Ontheia](https://ontheia.ai)** - Self-hosted, open-source AI agent platform
|
|
337
338
|
- **Zed, Replit, Codeium, Sourcegraph** - In development
|
|
338
339
|
- **Microsoft Copilot Studio** - Native MCP support with one-click server connections
|
|
339
340
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../../src/createServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,OAAO,EAAE,kBAAkB,EAAoB,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../../src/createServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,OAAO,EAAE,kBAAkB,EAAoB,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAoZzF"}
|
package/dist/src/createServer.js
CHANGED
|
@@ -91,6 +91,8 @@ export function createServer(vaultPath, options = {}) {
|
|
|
91
91
|
searchContent: { type: "boolean", description: "Search in note content (default: true)", default: true },
|
|
92
92
|
searchFrontmatter: { type: "boolean", description: "Search in frontmatter (default: false)", default: false },
|
|
93
93
|
caseSensitive: { type: "boolean", description: "Case sensitive search (default: false)", default: false },
|
|
94
|
+
pathPrefix: { type: "string", description: "Restrict the search to a vault subtree, e.g. \"Projects/2026\" (directory prefix)" },
|
|
95
|
+
excludePaths: { type: "array", items: { type: "string" }, description: "Skip files under these subtrees, e.g. [\"Archive\", \"meta\"] (directory prefixes)" },
|
|
94
96
|
prettyPrint: { type: "boolean", description: "Format JSON response with indentation (default: false)", default: false }
|
|
95
97
|
},
|
|
96
98
|
required: ["query"]
|
|
@@ -272,7 +274,9 @@ export function createServer(vaultPath, options = {}) {
|
|
|
272
274
|
limit: trimmedArgs.limit,
|
|
273
275
|
searchContent: trimmedArgs.searchContent,
|
|
274
276
|
searchFrontmatter: trimmedArgs.searchFrontmatter,
|
|
275
|
-
caseSensitive: trimmedArgs.caseSensitive
|
|
277
|
+
caseSensitive: trimmedArgs.caseSensitive,
|
|
278
|
+
pathPrefix: trimmedArgs.pathPrefix,
|
|
279
|
+
excludePaths: trimmedArgs.excludePaths
|
|
276
280
|
});
|
|
277
281
|
const indent = trimmedArgs.prettyPrint ? 2 : undefined;
|
|
278
282
|
return {
|
package/dist/src/filesystem.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { FrontmatterHandler } from './frontmatter.js';
|
|
2
2
|
import { PathFilter } from './pathfilter.js';
|
|
3
3
|
import type { ParsedNote, DirectoryListing, NoteWriteParams, DeleteNoteParams, DeleteResult, MoveNoteParams, MoveFileParams, MoveResult, BatchReadParams, BatchReadResult, UpdateFrontmatterParams, NoteInfo, TagManagementParams, TagManagementResult, PatchNoteParams, PatchNoteResult, VaultStats } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Map a filesystem write failure to a clear, accurate Error.
|
|
6
|
+
*
|
|
7
|
+
* Classifies by the Node error `code`, NOT by message substring. The old
|
|
8
|
+
* substring matching (`message.includes('space')`) mislabeled any error whose
|
|
9
|
+
* message merely contained "space" as a disk-full error, producing false
|
|
10
|
+
* "No space left on device" reports (#109). Errors we threw ourselves with a
|
|
11
|
+
* meaningful message (no `code`) pass through unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export declare function classifyWriteError(error: unknown, path: string): Error;
|
|
4
14
|
export declare class FileSystemService {
|
|
5
15
|
private vaultPath;
|
|
6
16
|
private frontmatterHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/filesystem.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,uBAAuB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzT,qBAAa,iBAAiB;IAK1B,OAAO,CAAC,SAAS;IAJnB,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,UAAU,CAAa;gBAGrB,SAAS,EAAE,MAAM,EACzB,UAAU,CAAC,EAAE,UAAU,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAazC,OAAO,CAAC,WAAW;IA6Db,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAgC3C,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/filesystem.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,uBAAuB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzT;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAiBtE;AAED,qBAAa,iBAAiB;IAK1B,OAAO,CAAC,SAAS;IAJnB,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,UAAU,CAAa;gBAGrB,SAAS,EAAE,MAAM,EACzB,UAAU,CAAC,EAAE,UAAU,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAazC,OAAO,CAAC,WAAW;IA6Db,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAgC3C,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA2EjD,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IA2F5D,aAAa,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8D3D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe3C,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAyG3D,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAoFrD,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA6HrD,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAgDpE,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjE,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA2ClD,UAAU,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAsG3E,YAAY,IAAI,MAAM;IAIhB,aAAa,CAAC,WAAW,GAAE,MAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAyD3D,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAkDpE"}
|
package/dist/src/filesystem.js
CHANGED
|
@@ -5,6 +5,33 @@ import trash from 'trash';
|
|
|
5
5
|
import { FrontmatterHandler } from './frontmatter.js';
|
|
6
6
|
import { PathFilter } from './pathfilter.js';
|
|
7
7
|
import { generateObsidianUri } from './uri.js';
|
|
8
|
+
/**
|
|
9
|
+
* Map a filesystem write failure to a clear, accurate Error.
|
|
10
|
+
*
|
|
11
|
+
* Classifies by the Node error `code`, NOT by message substring. The old
|
|
12
|
+
* substring matching (`message.includes('space')`) mislabeled any error whose
|
|
13
|
+
* message merely contained "space" as a disk-full error, producing false
|
|
14
|
+
* "No space left on device" reports (#109). Errors we threw ourselves with a
|
|
15
|
+
* meaningful message (no `code`) pass through unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export function classifyWriteError(error, path) {
|
|
18
|
+
const code = error instanceof Error ? error.code : undefined;
|
|
19
|
+
switch (code) {
|
|
20
|
+
case 'ENOSPC':
|
|
21
|
+
return new Error(`No space left on device: ${path}`);
|
|
22
|
+
case 'EACCES':
|
|
23
|
+
case 'EPERM':
|
|
24
|
+
return new Error(`Permission denied: ${path}`);
|
|
25
|
+
case 'EROFS':
|
|
26
|
+
return new Error(`Read-only filesystem: ${path}`);
|
|
27
|
+
}
|
|
28
|
+
// No filesystem code: an error we raised with a clear message (path
|
|
29
|
+
// traversal, validation, etc.). Preserve it as-is.
|
|
30
|
+
if (error instanceof Error && !code) {
|
|
31
|
+
return error;
|
|
32
|
+
}
|
|
33
|
+
return new Error(`Failed to write file: ${path} - ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
34
|
+
}
|
|
8
35
|
export class FileSystemService {
|
|
9
36
|
vaultPath;
|
|
10
37
|
frontmatterHandler;
|
|
@@ -170,15 +197,7 @@ export class FileSystemService {
|
|
|
170
197
|
await writeFile(fullPath, finalContent, 'utf-8');
|
|
171
198
|
}
|
|
172
199
|
catch (error) {
|
|
173
|
-
|
|
174
|
-
if (error.message.includes('permission') || error.message.includes('access')) {
|
|
175
|
-
throw new Error(`Permission denied: ${path}`);
|
|
176
|
-
}
|
|
177
|
-
if (error.message.includes('space') || error.message.includes('ENOSPC')) {
|
|
178
|
-
throw new Error(`No space left on device: ${path}`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
throw new Error(`Failed to write file: ${path} - ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
200
|
+
throw classifyWriteError(error, path);
|
|
182
201
|
}
|
|
183
202
|
}
|
|
184
203
|
async patchNote(params) {
|
package/dist/src/pathfilter.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pathfilter.d.ts","sourceRoot":"","sources":["../../src/pathfilter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,UAAU;
|
|
1
|
+
{"version":3,"file":"pathfilter.d.ts","sourceRoot":"","sources":["../../src/pathfilter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,UAAU;IAOrB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAMxC;IAEH,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,iBAAiB,CAAW;gBAExB,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAuB9C,OAAO,CAAC,eAAe;IAoBvB;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAQ5B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAyBhC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAY1C,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,MAAM;IA0Bd,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;CAGvC"}
|
package/dist/src/pathfilter.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
export class PathFilter {
|
|
2
|
+
// Restricted directory/file names denied at ANY depth, not just the vault
|
|
3
|
+
// root. The glob patterns below are anchored, so `node_modules/**` only
|
|
4
|
+
// matched a root-level node_modules; nested ones (e.g.
|
|
5
|
+
// `tools/cli/node_modules/...`) were traversed, polluting the tag index, and
|
|
6
|
+
// nested `.git`/`.obsidian` leaked their contents (#128). Names are compared
|
|
7
|
+
// lowercased against each path segment.
|
|
8
|
+
static RESTRICTED_SEGMENTS = new Set([
|
|
9
|
+
'.obsidian',
|
|
10
|
+
'.git',
|
|
11
|
+
'node_modules',
|
|
12
|
+
'.ds_store',
|
|
13
|
+
'thumbs.db',
|
|
14
|
+
]);
|
|
2
15
|
ignoredPatterns;
|
|
3
16
|
allowedExtensions;
|
|
4
17
|
constructor(config) {
|
|
@@ -84,6 +97,13 @@ export class PathFilter {
|
|
|
84
97
|
// (".Git/config", ".git./config", ".git /config") cannot bypass the deny-list
|
|
85
98
|
// on case-insensitive / Windows filesystems.
|
|
86
99
|
const canonicalPath = this.canonicalizeForMatch(normalizedPath);
|
|
100
|
+
// Deny restricted directories/files at any depth: if any path segment is a
|
|
101
|
+
// restricted name, the path is ignored regardless of nesting (#128).
|
|
102
|
+
for (const segment of canonicalPath.split('/')) {
|
|
103
|
+
if (PathFilter.RESTRICTED_SEGMENTS.has(segment.toLowerCase())) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
87
107
|
// Check if path matches any ignored pattern
|
|
88
108
|
for (const pattern of this.ignoredPatterns) {
|
|
89
109
|
if (this.simpleGlobMatch(pattern, normalizedPath) ||
|
package/dist/src/search.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAiB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAiB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc5E,qBAAa,aAAa;IAKtB,OAAO,CAAC,UAAU;IAJpB,OAAO,CAAC,SAAS,CAAS;gBAGxB,SAAS,EAAE,MAAM,EACT,UAAU,EAAE,UAAU;IAK1B,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;YAqK7C,iBAAiB;IAwB/B,OAAO,CAAC,MAAM;CA0Bf"}
|
package/dist/src/search.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { join, resolve } from 'path';
|
|
2
2
|
import { readFile, readdir } from 'node:fs/promises';
|
|
3
3
|
import { generateObsidianUri } from './uri.js';
|
|
4
|
+
/** Normalize a subtree path: forward slashes, no leading/trailing slashes. */
|
|
5
|
+
function normalizeSubtree(p) {
|
|
6
|
+
return p.replace(/\\/g, '/').replace(/^\/+/, '').replace(/\/+$/, '');
|
|
7
|
+
}
|
|
8
|
+
/** True if a vault-relative path is the subtree itself or sits under it. */
|
|
9
|
+
function isUnderSubtree(relativePath, subtree) {
|
|
10
|
+
if (!subtree)
|
|
11
|
+
return false;
|
|
12
|
+
return relativePath === subtree || relativePath.startsWith(subtree + '/');
|
|
13
|
+
}
|
|
4
14
|
export class SearchService {
|
|
5
15
|
pathFilter;
|
|
6
16
|
vaultPath;
|
|
@@ -9,10 +19,12 @@ export class SearchService {
|
|
|
9
19
|
this.vaultPath = resolve(vaultPath);
|
|
10
20
|
}
|
|
11
21
|
async search(params) {
|
|
12
|
-
const { query, limit = 5, searchContent = true, searchFrontmatter = false, caseSensitive = false } = params;
|
|
22
|
+
const { query, limit = 5, searchContent = true, searchFrontmatter = false, caseSensitive = false, pathPrefix, excludePaths } = params;
|
|
13
23
|
if (!query || query.trim().length === 0) {
|
|
14
24
|
throw new Error('Search query cannot be empty');
|
|
15
25
|
}
|
|
26
|
+
const normalizedPrefix = pathPrefix ? normalizeSubtree(pathPrefix) : '';
|
|
27
|
+
const normalizedExcludes = (excludePaths || []).map(normalizeSubtree).filter(Boolean);
|
|
16
28
|
const maxLimit = Math.min(limit, 20);
|
|
17
29
|
// Corpus stats for reranking
|
|
18
30
|
let totalDocLength = 0;
|
|
@@ -29,9 +41,14 @@ export class SearchService {
|
|
|
29
41
|
const allowedFiles = [];
|
|
30
42
|
for (const fullPath of markdownFiles) {
|
|
31
43
|
const relativePath = fullPath.substring(prefixLen).replace(/\\/g, '/');
|
|
32
|
-
if (this.pathFilter.isAllowed(relativePath))
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
if (!this.pathFilter.isAllowed(relativePath))
|
|
45
|
+
continue;
|
|
46
|
+
// Scope to the requested subtree, and skip excluded subtrees, before I/O
|
|
47
|
+
if (normalizedPrefix && !isUnderSubtree(relativePath, normalizedPrefix))
|
|
48
|
+
continue;
|
|
49
|
+
if (normalizedExcludes.some(ex => isUnderSubtree(relativePath, ex)))
|
|
50
|
+
continue;
|
|
51
|
+
allowedFiles.push({ fullPath, relativePath });
|
|
35
52
|
}
|
|
36
53
|
// Read files in parallel batches
|
|
37
54
|
const BATCH_SIZE = 5;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export interface SearchParams {
|
|
|
51
51
|
searchContent?: boolean;
|
|
52
52
|
searchFrontmatter?: boolean;
|
|
53
53
|
caseSensitive?: boolean;
|
|
54
|
+
/** Restrict the search to a vault subtree (directory prefix, e.g. "Projects/2026"). */
|
|
55
|
+
pathPrefix?: string;
|
|
56
|
+
/** Skip files under any of these subtrees (directory prefixes). */
|
|
57
|
+
excludePaths?: string[];
|
|
54
58
|
}
|
|
55
59
|
export interface SearchResult {
|
|
56
60
|
p: string;
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAGD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,KAAK,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED