obsidian-mcp-server 3.7.0 → 3.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/AGENTS.md +31 -11
  2. package/CLAUDE.md +31 -11
  3. package/Dockerfile +10 -3
  4. package/README.md +30 -91
  5. package/changelog/3.7.x/3.7.1.md +40 -0
  6. package/changelog/3.7.x/3.7.2.md +34 -0
  7. package/dist/config/server-config.js +1 -1
  8. package/dist/config/server-config.js.map +1 -1
  9. package/dist/index.js +13 -32
  10. package/dist/index.js.map +1 -1
  11. package/dist/instructions.d.ts +20 -0
  12. package/dist/instructions.d.ts.map +1 -0
  13. package/dist/instructions.js +40 -0
  14. package/dist/instructions.js.map +1 -0
  15. package/dist/mcp-server/tools/definitions/_shared/markdown.d.ts +14 -0
  16. package/dist/mcp-server/tools/definitions/_shared/markdown.d.ts.map +1 -0
  17. package/dist/mcp-server/tools/definitions/_shared/markdown.js +17 -0
  18. package/dist/mcp-server/tools/definitions/_shared/markdown.js.map +1 -0
  19. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts +39 -0
  20. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +63 -2
  22. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/index.d.ts +127 -116
  24. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +6 -0
  26. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +15 -6
  28. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
  29. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -1
  30. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +5 -4
  31. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
  32. package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js +2 -1
  34. package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
  36. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +51 -40
  37. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
  38. package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.d.ts.map +1 -1
  39. package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js +7 -4
  40. package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js.map +1 -1
  41. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -1
  42. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +7 -6
  43. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
  44. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts.map +1 -1
  45. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +3 -2
  46. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -1
  47. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -1
  48. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +13 -9
  49. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
  50. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
  51. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +9 -5
  52. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
  53. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -1
  54. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +2 -1
  55. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -1
  56. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -1
  57. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +5 -4
  58. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -1
  59. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -1
  60. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +12 -4
  61. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
  62. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +26 -2
  63. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -1
  64. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +61 -34
  65. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
  66. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +5 -0
  67. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
  68. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +24 -6
  69. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
  70. package/dist/services/obsidian/frontmatter-ops.d.ts +15 -1
  71. package/dist/services/obsidian/frontmatter-ops.d.ts.map +1 -1
  72. package/dist/services/obsidian/frontmatter-ops.js +55 -10
  73. package/dist/services/obsidian/frontmatter-ops.js.map +1 -1
  74. package/dist/services/obsidian/jsonlogic-evaluator.d.ts +83 -0
  75. package/dist/services/obsidian/jsonlogic-evaluator.d.ts.map +1 -0
  76. package/dist/services/obsidian/jsonlogic-evaluator.js +192 -0
  77. package/dist/services/obsidian/jsonlogic-evaluator.js.map +1 -0
  78. package/dist/services/obsidian/jsonlogic-worker.d.ts +53 -0
  79. package/dist/services/obsidian/jsonlogic-worker.d.ts.map +1 -0
  80. package/dist/services/obsidian/jsonlogic-worker.js +237 -0
  81. package/dist/services/obsidian/jsonlogic-worker.js.map +1 -0
  82. package/dist/services/obsidian/obsidian-service.d.ts +56 -8
  83. package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
  84. package/dist/services/obsidian/obsidian-service.js +254 -48
  85. package/dist/services/obsidian/obsidian-service.js.map +1 -1
  86. package/dist/services/obsidian/path-policy.d.ts +33 -5
  87. package/dist/services/obsidian/path-policy.d.ts.map +1 -1
  88. package/dist/services/obsidian/path-policy.js +99 -17
  89. package/dist/services/obsidian/path-policy.js.map +1 -1
  90. package/dist/services/obsidian/types.d.ts +12 -3
  91. package/dist/services/obsidian/types.d.ts.map +1 -1
  92. package/manifest.json +2 -2
  93. package/package.json +20 -15
  94. package/server.json +5 -5
@@ -0,0 +1,192 @@
1
+ /**
2
+ * @fileoverview Server-side JSONLogic evaluation for searches scoped by
3
+ * OBSIDIAN_READ_PATHS. The caller's tree runs here, on a worker thread, over
4
+ * the readable notes alone, instead of upstream over the whole vault: no hit,
5
+ * result, or error reads a note outside the read scope. The notes' link
6
+ * fields arrive cut to readable entries, but which note a link resolves to is
7
+ * still Obsidian's vault-wide resolution (#165).
8
+ *
9
+ * Every evaluation is bounded — tree depth, work budgets the worker enforces
10
+ * (per note for what each note's evaluation builds, per search for what kept
11
+ * results hold past a 1,024-character allowance each), and a wall-clock
12
+ * deadline — and an evaluation past a bound fails with `logic_too_costly`
13
+ * rather than holding the process. A note nested too deep to hand to the
14
+ * worker fails with `note_too_deep`.
15
+ *
16
+ * @module services/obsidian/jsonlogic-evaluator
17
+ */
18
+ import { Worker } from 'node:worker_threads';
19
+ import { serializationError, validationError } from '@cyanheads/mcp-ts-core/errors';
20
+ /**
21
+ * Deepest object/array nesting a tree may have. The plugin evaluates every
22
+ * shape to at least 5,000 levels; this stays well under the depth at which
23
+ * Node's structured clone overflows the stack handing a tree to the worker
24
+ * (about 3,500 levels).
25
+ */
26
+ export const MAX_TREE_DEPTH = 1_000;
27
+ /**
28
+ * Work units kept results may hold across one search, every batch included
29
+ * (see the worker's `chargeKept`). A result whose JSON is at most 1,024
30
+ * characters is kept free, whatever its note; a larger one pays for what its
31
+ * JSON holds beyond its own note's JSON. Kept results live until the search
32
+ * answers, so this bounds what an evaluation retains, since Bun ignores the
33
+ * worker's `resourceLimits`. What a note's evaluation builds and drops is
34
+ * bounded per note by {@link NOTE_BUILD_UNITS}; evaluation steps that build
35
+ * nothing are bounded by {@link EVALUATION_DEADLINE_MS}, so a tree that only
36
+ * tests note fields spends nothing however many notes it reads.
37
+ */
38
+ export const KEPT_RESULT_UNITS = 10_000_000;
39
+ /**
40
+ * Work units one note's evaluation may build beyond the note's own size (see
41
+ * the worker's `charge`): the size of every value `merge`, `cat`, or `map`
42
+ * builds and of every value an operator places in an array literal. The
43
+ * allowance resets for each note, since what an evaluation builds is dropped
44
+ * when it ends, so a tree that builds from every note of a broad scope is
45
+ * bounded by its largest note rather than by the scope's total. Adding the
46
+ * note's own size means one copy of a note always fits, at any size a batch
47
+ * carries; the fixed part leaves room for dozens of copies of a 200 KB note
48
+ * while holding what one evaluation can allocate to the note plus
49
+ * 10,000,000 units.
50
+ */
51
+ export const NOTE_BUILD_UNITS = 10_000_000;
52
+ /** Wall-clock ceiling on one search's evaluation, across its batches, worker startup included. */
53
+ export const EVALUATION_DEADLINE_MS = 10_000;
54
+ /**
55
+ * The worker's module, next to this one: `.js` in the build, `.ts` when the
56
+ * test suite runs the source, which both Bun and Node load directly.
57
+ */
58
+ const WORKER_URL = new URL(`./jsonlogic-worker.${import.meta.url.endsWith('.ts') ? 'ts' : 'js'}`, import.meta.url);
59
+ /**
60
+ * Whether the plugin would read note bodies for `logic`: its own rule, a
61
+ * substring test for `"content"` on the tree's JSON. A tree without it sees
62
+ * `content` as `""` upstream, so a scoped fetch mirrors the same rule to keep
63
+ * results identical — and it is conservative, firing on the word anywhere.
64
+ */
65
+ export function readsContent(logic) {
66
+ return JSON.stringify(logic).includes('"content"');
67
+ }
68
+ /**
69
+ * Reject a tree nested deeper than {@link MAX_TREE_DEPTH} before it reaches
70
+ * anything recursive (serialization, the worker hand-off, evaluation).
71
+ */
72
+ export function assertTreeDepth(logic) {
73
+ if (nestingDepth(logic, MAX_TREE_DEPTH) > MAX_TREE_DEPTH) {
74
+ throw tooCostly(`The JSONLogic tree nests deeper than ${MAX_TREE_DEPTH.toLocaleString('en-US')} levels.`);
75
+ }
76
+ }
77
+ /**
78
+ * Deepest object/array nesting in `value`, which is level 1, measured until
79
+ * it passes `limit`. Iterative, so it measures data too deep for any
80
+ * recursive walk.
81
+ */
82
+ function nestingDepth(value, limit = Number.POSITIVE_INFINITY) {
83
+ let deepest = 0;
84
+ const pending = [[value, 1]];
85
+ while (pending.length > 0 && deepest <= limit) {
86
+ const [node, depth] = pending.pop();
87
+ if (node === null || typeof node !== 'object')
88
+ continue;
89
+ deepest = Math.max(deepest, depth);
90
+ for (const child of Object.values(node))
91
+ pending.push([child, depth + 1]);
92
+ }
93
+ return deepest;
94
+ }
95
+ /**
96
+ * One search's evaluation of `logic`. `evaluate` takes the readable notes in
97
+ * vault order, all at once or in successive batches; the budget for kept
98
+ * results and the deadline span every batch, and each note's build allowance
99
+ * is its own, so batching changes memory use, not results.
100
+ * Each call returns the batch's hits as the plugin's search would: a hit for
101
+ * every truthy result, results shaped by a JSON round trip. It throws
102
+ * `logic_invalid` when the tree fails on a note, `logic_too_costly` past
103
+ * either budget or the deadline, `note_too_deep` for a note the worker
104
+ * hand-off cannot carry, and the abort reason when `signal` aborts first.
105
+ */
106
+ export function createJsonLogicEvaluation(logic, opts = {}) {
107
+ const { signal, deadlineMs = EVALUATION_DEADLINE_MS } = opts;
108
+ let keptUnitsLeft = KEPT_RESULT_UNITS;
109
+ let msLeft = deadlineMs;
110
+ const pastDeadline = () => tooCostly(`Evaluating the JSONLogic tree over the readable notes ran past ${deadlineMs / 1000} s.`);
111
+ return {
112
+ async evaluate(notes) {
113
+ if (notes.length === 0)
114
+ return [];
115
+ signal?.throwIfAborted();
116
+ if (msLeft <= 0)
117
+ throw pastDeadline();
118
+ const started = performance.now();
119
+ const response = await runWorker({ logic, notes, keptUnits: keptUnitsLeft, noteUnits: NOTE_BUILD_UNITS }, msLeft, pastDeadline, signal);
120
+ msLeft -= performance.now() - started;
121
+ if (response.ok) {
122
+ keptUnitsLeft = response.keptUnitsLeft;
123
+ return response.hits.map((hit) => ({
124
+ filename: hit.filename,
125
+ result: JSON.parse(hit.json),
126
+ }));
127
+ }
128
+ throw failureError(response);
129
+ },
130
+ };
131
+ }
132
+ function failureError(response) {
133
+ const cause = new Error(response.detail);
134
+ switch (response.failure) {
135
+ case 'invalid_regexp':
136
+ return validationError('A `regexp` operand in the JSONLogic tree did not compile. `regexp` takes `[PATTERN, VALUE]` — with the operands reversed, the note field is compiled as the pattern.', { reason: 'logic_invalid' }, { cause });
137
+ case 'invalid':
138
+ return validationError('The JSONLogic tree could not be evaluated.', { reason: 'logic_invalid' }, { cause });
139
+ case 'over_note_budget':
140
+ return tooCostly(`Evaluating the JSONLogic tree on one readable note built more than the per-note work budget of ${NOTE_BUILD_UNITS.toLocaleString('en-US')} units beyond that note's own size.`);
141
+ case 'over_kept_budget':
142
+ return tooCostly(`The JSONLogic tree's results over the readable notes held more than the search's work budget of ${KEPT_RESULT_UNITS.toLocaleString('en-US')} units: each result over 1,024 characters pays for what it holds beyond its own note's size.`);
143
+ }
144
+ }
145
+ /** One worker per batch, terminated however it ends. */
146
+ async function runWorker(request, deadlineMs, pastDeadline, signal) {
147
+ const worker = new Worker(WORKER_URL);
148
+ const { promise, resolve, reject } = Promise.withResolvers();
149
+ const timer = setTimeout(() => reject(pastDeadline()), deadlineMs);
150
+ const onAbort = () => reject(signal?.reason);
151
+ signal?.addEventListener('abort', onAbort, { once: true });
152
+ worker.once('message', resolve);
153
+ worker.once('error', reject);
154
+ worker.once('exit', (code) => reject(new Error(`JSONLogic worker exited with code ${code} before answering`)));
155
+ try {
156
+ worker.postMessage(request);
157
+ }
158
+ catch (err) {
159
+ // Rejected before the await below takes the promise, so the exit `terminate` raises settles nothing.
160
+ reject(handOffError(err, request.notes));
161
+ }
162
+ try {
163
+ return await promise;
164
+ }
165
+ finally {
166
+ clearTimeout(timer);
167
+ signal?.removeEventListener('abort', onAbort);
168
+ await worker.terminate();
169
+ }
170
+ }
171
+ /**
172
+ * Why `postMessage` refused a batch. Structured clone recurses, so data
173
+ * nested deep enough overflows the stack: about 3,500 levels under Node,
174
+ * tens of thousands under Bun. The tree is held to {@link MAX_TREE_DEPTH},
175
+ * so the deepest note is the one that did not fit. Any other refusal is
176
+ * returned as it came.
177
+ */
178
+ function handOffError(err, notes) {
179
+ if (!(err instanceof RangeError))
180
+ return err;
181
+ let deepest = { path: '', levels: 0 };
182
+ for (const note of notes) {
183
+ const levels = nestingDepth(note);
184
+ if (levels > deepest.levels)
185
+ deepest = { path: note.path, levels };
186
+ }
187
+ return serializationError(`The readable note "${deepest.path}" holds data nested ${deepest.levels.toLocaleString('en-US')} levels deep, too deep for the server to hand to its evaluator.`, { reason: 'note_too_deep', path: deepest.path }, { cause: err });
188
+ }
189
+ function tooCostly(message) {
190
+ return validationError(message, { reason: 'logic_too_costly' });
191
+ }
192
+ //# sourceMappingURL=jsonlogic-evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonlogic-evaluator.js","sourceRoot":"","sources":["../../../src/services/obsidian/jsonlogic-evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview Worker-thread entry that evaluates a caller's JSONLogic tree
3
+ * against note contexts, for searches scoped by OBSIDIAN_READ_PATHS. Runs the
4
+ * operator set the Local REST API plugin runs (json-logic-js 2.0.5 plus its
5
+ * `glob` and `regexp`), with the plugin's hit test and JSON-shaped results, so
6
+ * a scoped search answers as the plugin would over the same notes.
7
+ *
8
+ * Off the main thread so a slow tree cannot hold the event loop: the evaluator
9
+ * terminates this worker at its deadline, which also stops a native regex
10
+ * mid-backtrack. Memory is bounded here by work budgets, since Bun ignores
11
+ * `resourceLimits`: one per note for what its evaluation builds and drops,
12
+ * and one across the search for what kept results hold past a
13
+ * 1,024-character allowance each.
14
+ *
15
+ * Imports only packages and builtins, never sibling modules: under Node the
16
+ * test suite loads this file from source, where `./x.js` specifiers do not
17
+ * resolve to `.ts`.
18
+ *
19
+ * @module services/obsidian/jsonlogic-worker
20
+ */
21
+ /** A note as the plugin's JSONLogic search evaluates it, link fields already scoped. */
22
+ export interface NoteContext {
23
+ path: string;
24
+ [field: string]: unknown;
25
+ }
26
+ export interface EvaluationRequest {
27
+ /** Work units left for kept results, across every batch of the search; see {@link chargeKept}. */
28
+ keptUnits: number;
29
+ logic: unknown;
30
+ notes: NoteContext[];
31
+ /** Work units each note's evaluation may build beyond the note's own size; see {@link charge}. */
32
+ noteUnits: number;
33
+ }
34
+ /**
35
+ * How an evaluation ended. `json` is the hit's result serialized as the
36
+ * plugin's response would carry it; `keptUnitsLeft` carries into the next
37
+ * batch.
38
+ */
39
+ export type EvaluationResponse = {
40
+ ok: true;
41
+ hits: Array<{
42
+ filename: string;
43
+ json: string;
44
+ }>;
45
+ keptUnitsLeft: number;
46
+ } | {
47
+ ok: false;
48
+ failure: 'invalid' | 'invalid_regexp' | BudgetFailure;
49
+ detail: string;
50
+ };
51
+ type BudgetFailure = 'over_note_budget' | 'over_kept_budget';
52
+ export {};
53
+ //# sourceMappingURL=jsonlogic-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonlogic-worker.d.ts","sourceRoot":"","sources":["../../../src/services/obsidian/jsonlogic-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,kGAAkG;IAClG,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,kGAAkG;IAClG,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACpF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,SAAS,GAAG,gBAAgB,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF,KAAK,aAAa,GAAG,kBAAkB,GAAG,kBAAkB,CAAC"}
@@ -0,0 +1,237 @@
1
+ /**
2
+ * @fileoverview Worker-thread entry that evaluates a caller's JSONLogic tree
3
+ * against note contexts, for searches scoped by OBSIDIAN_READ_PATHS. Runs the
4
+ * operator set the Local REST API plugin runs (json-logic-js 2.0.5 plus its
5
+ * `glob` and `regexp`), with the plugin's hit test and JSON-shaped results, so
6
+ * a scoped search answers as the plugin would over the same notes.
7
+ *
8
+ * Off the main thread so a slow tree cannot hold the event loop: the evaluator
9
+ * terminates this worker at its deadline, which also stops a native regex
10
+ * mid-backtrack. Memory is bounded here by work budgets, since Bun ignores
11
+ * `resourceLimits`: one per note for what its evaluation builds and drops,
12
+ * and one across the search for what kept results hold past a
13
+ * 1,024-character allowance each.
14
+ *
15
+ * Imports only packages and builtins, never sibling modules: under Node the
16
+ * test suite loads this file from source, where `./x.js` specifiers do not
17
+ * resolve to `.ts`.
18
+ *
19
+ * @module services/obsidian/jsonlogic-worker
20
+ */
21
+ import { parentPort } from 'node:worker_threads';
22
+ import globToRegExp from 'glob-to-regexp';
23
+ import jsonLogic from 'json-logic-js';
24
+ /** Thrown when a work budget runs out; never caught by json-logic-js, which has no try. */
25
+ class BudgetExhausted extends Error {
26
+ failure;
27
+ constructor(failure) {
28
+ super(failure);
29
+ this.failure = failure;
30
+ }
31
+ }
32
+ /** Units the current note's evaluation may still build; reset for every note. */
33
+ let noteUnitsLeft = 0;
34
+ /** Units kept results may still hold, across the whole search. */
35
+ let keptUnitsLeft = 0;
36
+ /**
37
+ * Spend `units` of the current note's budget, which bounds the memory one
38
+ * note's evaluation allocates; the deadline bounds time. The budget is the
39
+ * note's own {@link weight} plus `noteUnits`, so a tree can always build a
40
+ * copy of what the note holds, and it resets for the next note: what one
41
+ * note's evaluation builds is dropped when it ends, unless it is kept, which
42
+ * {@link chargeKept} bounds across the search. Only what a tree builds is
43
+ * charged, at its {@link weight}: `merge` and `cat` before they build, a `map`
44
+ * result, and the elements operators placed in an array literal
45
+ * ({@link literalWeight}). Every other step allocates no more than its
46
+ * operands already hold — comparisons, `var`, `in`, `missing`, `some` / `all`
47
+ * / `none`, arithmetic, `substr`, `glob`, and `regexp` return a primitive, a
48
+ * reference, or a string conversion of a value that was charged, is the
49
+ * note's, or is written in the tree; `filter` returns part of its input, and
50
+ * `if`, `and`, `or`, and `reduce` return a value another step produced — so
51
+ * evaluation steps cost nothing. Charging what is built bounds what a tree
52
+ * can allocate, including by multiplying references to one large string, and
53
+ * so bounds every later string conversion of what it built.
54
+ */
55
+ function charge(units) {
56
+ noteUnitsLeft -= units;
57
+ if (noteUnitsLeft < 0)
58
+ throw new BudgetExhausted('over_note_budget');
59
+ }
60
+ /** Spend `units` of the search's budget for kept results, which outlive their note's evaluation. */
61
+ function chargeKept(units) {
62
+ keptUnitsLeft -= units;
63
+ if (keptUnitsLeft < 0)
64
+ throw new BudgetExhausted('over_kept_budget');
65
+ }
66
+ /** Length of a plain object's string conversion, `[object Object]`. */
67
+ const OBJECT_STRING_CHARS = 15;
68
+ /**
69
+ * Size of a value in work units, counted until it passes `limit`: one per
70
+ * node plus the length of the node's own string conversion — a string's
71
+ * length, `String(value).length` for a number, boolean, `null`, or
72
+ * `undefined`, and {@link OBJECT_STRING_CHARS} plus its keys' lengths for an
73
+ * object. An array converts to its elements joined by commas, which the
74
+ * per-node unit covers, so no value converts to a string longer than its
75
+ * weight. Iterative, because a `reduce` can nest values deeper than the call
76
+ * stack.
77
+ */
78
+ function weight(value, limit) {
79
+ let total = 0;
80
+ const pending = [value];
81
+ while (pending.length > 0 && total <= limit) {
82
+ const next = pending.pop();
83
+ total += 1;
84
+ if (typeof next === 'string')
85
+ total += next.length;
86
+ // Pushed one by one: spreading a long array overruns the argument limit.
87
+ else if (Array.isArray(next))
88
+ for (const item of next)
89
+ pending.push(item);
90
+ else if (next !== null && typeof next === 'object') {
91
+ total += OBJECT_STRING_CHARS;
92
+ for (const [key, field] of Object.entries(next)) {
93
+ total += key.length;
94
+ pending.push(field);
95
+ }
96
+ }
97
+ else
98
+ total += String(next).length;
99
+ }
100
+ return total;
101
+ }
102
+ /**
103
+ * Size of the array an array literal just built, in work units. An element
104
+ * written in the tree — a primitive, or an array literal charged at its own
105
+ * application — adds nothing: its slot and a literal string's length are
106
+ * bounded by the request, and the string is shared rather than copied. An
107
+ * element an operator produced pays its full {@link weight}.
108
+ */
109
+ function literalWeight(logic, built) {
110
+ let total = 0;
111
+ for (let i = 0; i < logic.length && total <= noteUnitsLeft; i++) {
112
+ const element = logic[i];
113
+ if (element !== null && typeof element === 'object' && !Array.isArray(element)) {
114
+ total += weight(built[i], noteUnitsLeft - total);
115
+ }
116
+ }
117
+ return total;
118
+ }
119
+ const baseApply = jsonLogic.apply;
120
+ /**
121
+ * json-logic-js recurses through `jsonLogic.apply`, so this wrapper sees every
122
+ * application. A `map` result is charged its size: mapping over a long array
123
+ * to a constant multiplies references to it without building anything the
124
+ * other charges see.
125
+ */
126
+ jsonLogic.apply = (logic, data) => {
127
+ const result = baseApply(logic, data);
128
+ if (Array.isArray(logic))
129
+ charge(literalWeight(logic, result));
130
+ else if (isMap(logic))
131
+ charge(weight(result, noteUnitsLeft));
132
+ return result;
133
+ };
134
+ /** A `map` application, by json-logic-js's own test: an object with one key. */
135
+ function isMap(logic) {
136
+ return (logic !== null &&
137
+ typeof logic === 'object' &&
138
+ Object.hasOwn(logic, 'map') &&
139
+ Object.keys(logic).length === 1);
140
+ }
141
+ /** The plugin's two operators, as Local REST API 5.x registers them: pattern first, `false` for a non-string operand. */
142
+ jsonLogic.add_operation('glob', (pattern, field) => typeof field === 'string' && typeof pattern === 'string'
143
+ ? globToRegExp(pattern).test(field)
144
+ : false);
145
+ jsonLogic.add_operation('regexp', (pattern, field) => typeof field === 'string' && typeof pattern === 'string'
146
+ ? new RegExp(pattern).test(field)
147
+ : false);
148
+ /** json-logic-js's `log` writes to stdout, which is the JSON-RPC stream under stdio. Same value, no write. */
149
+ jsonLogic.add_operation('log', (value) => value);
150
+ /**
151
+ * json-logic-js's `var`, reading own properties only: inherited properties are
152
+ * out of reach, and own properties still cover every note field, array index,
153
+ * and `length`.
154
+ */
155
+ jsonLogic.add_operation('var', function (key, fallback) {
156
+ const notFound = fallback === undefined ? null : fallback;
157
+ if (key === undefined || key === '' || key === null)
158
+ return this;
159
+ let data = this;
160
+ for (const segment of String(key).split('.')) {
161
+ if (data === null || data === undefined || !Object.hasOwn(Object(data), segment)) {
162
+ return notFound;
163
+ }
164
+ data = data[segment];
165
+ if (data === undefined)
166
+ return notFound;
167
+ }
168
+ return data;
169
+ });
170
+ /** Stock `merge` and `cat`, charged before they build, so an oversized value is never allocated. */
171
+ jsonLogic.add_operation('merge', (...args) => {
172
+ for (const arg of args)
173
+ charge(weight(arg, noteUnitsLeft));
174
+ return args.reduce((all, next) => all.concat(next), []);
175
+ });
176
+ jsonLogic.add_operation('cat', (...args) => {
177
+ for (const arg of args)
178
+ charge(weight(arg, noteUnitsLeft));
179
+ return args.join('');
180
+ });
181
+ /** The plugin's hit test: `null`/`undefined`, `[]`, and `{}` drop a note. */
182
+ function isTruthy(value) {
183
+ if (value === undefined || value === null)
184
+ return false;
185
+ if (Array.isArray(value))
186
+ return value.length > 0;
187
+ if (typeof value === 'object')
188
+ return Object.keys(value).length > 0;
189
+ return Boolean(value);
190
+ }
191
+ /**
192
+ * Serialized characters a kept result may hold with no charge, whatever its
193
+ * note's size, so ordinary results skip the comparison below.
194
+ */
195
+ const FREE_RESULT_CHARS = 1_024;
196
+ /**
197
+ * Evaluate `request.logic` against each note in order, as the plugin's search
198
+ * loop does, each note with a fresh budget for what it builds. A kept result
199
+ * is held until the search answers. One whose JSON is at most
200
+ * {@link FREE_RESULT_CHARS} is free; a larger one pays the search's budget for
201
+ * whatever it holds beyond its own note's serialized size: a result drawn
202
+ * from the note stays free, while one repeating the tree's large constants on
203
+ * every note is bounded across the search.
204
+ */
205
+ function evaluate(request) {
206
+ keptUnitsLeft = request.keptUnits;
207
+ const hits = [];
208
+ for (const note of request.notes) {
209
+ noteUnitsLeft = request.noteUnits + weight(note, Number.POSITIVE_INFINITY);
210
+ try {
211
+ const result = jsonLogic.apply(request.logic, note);
212
+ if (!isTruthy(result))
213
+ continue;
214
+ const json = JSON.stringify(result);
215
+ if (json.length > FREE_RESULT_CHARS) {
216
+ chargeKept(Math.max(0, json.length - JSON.stringify(note).length));
217
+ }
218
+ hits.push({ filename: note.path, json });
219
+ }
220
+ catch (err) {
221
+ if (err instanceof BudgetExhausted) {
222
+ return { ok: false, failure: err.failure, detail: 'work budget exhausted' };
223
+ }
224
+ const detail = err instanceof Error ? err.message : String(err);
225
+ return {
226
+ ok: false,
227
+ failure: /invalid regular expression/i.test(detail) ? 'invalid_regexp' : 'invalid',
228
+ detail,
229
+ };
230
+ }
231
+ }
232
+ return { ok: true, hits, keptUnitsLeft };
233
+ }
234
+ parentPort?.once('message', (request) => {
235
+ parentPort?.postMessage(evaluate(request));
236
+ });
237
+ //# sourceMappingURL=jsonlogic-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonlogic-worker.js","sourceRoot":"","sources":["../../../src/services/obsidian/jsonlogic-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,SAAS,MAAM,eAAe,CAAC;AA4BtC,2FAA2F;AAC3F,MAAM,eAAgB,SAAQ,KAAK;IACxB,OAAO,CAAgB;IAChC,YAAY,OAAsB;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,iFAAiF;AACjF,IAAI,aAAa,GAAG,CAAC,CAAC;AACtB,kEAAkE;AAClE,IAAI,aAAa,GAAG,CAAC,CAAC;AAEtB;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,MAAM,CAAC,KAAa;IAC3B,aAAa,IAAI,KAAK,CAAC;IACvB,IAAI,aAAa,GAAG,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,oGAAoG;AACpG,SAAS,UAAU,CAAC,KAAa;IAC/B,aAAa,IAAI,KAAK,CAAC;IACvB,IAAI,aAAa,GAAG,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,uEAAuE;AACvE,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B;;;;;;;;;GASG;AACH,SAAS,MAAM,CAAC,KAAc,EAAE,KAAa;IAC3C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,OAAO,GAAc,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,CAAC;QACX,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QACnD,yEAAyE;aACpE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,KAAK,MAAM,IAAI,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACrE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnD,KAAK,IAAI,mBAAmB,CAAC;YAC7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;;YAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,KAAgB,EAAE,KAAgB;IACvD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,IAAI,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QAChE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/E,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,GAAG,KAAK,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC;AAClC;;;;;GAKG;AACH,SAAS,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAChC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAmB,CAAC,CAAC,CAAC;SACvE,IAAI,KAAK,CAAC,KAAK,CAAC;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IAC7D,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,gFAAgF;AAChF,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAChC,CAAC;AACJ,CAAC;AAED,yHAAyH;AACzH,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CACjD,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ;IACtD,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACnC,CAAC,CAAC,KAAK,CACV,CAAC;AACF,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CACnD,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ;IACtD,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjC,CAAC,CAAC,KAAK,CACV,CAAC;AAEF,8GAA8G;AAC9G,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAEjD;;;;GAIG;AACH,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,UAAyB,GAAY,EAAE,QAAiB;IACrF,MAAM,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1D,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;YACjF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,GAAI,IAAgC,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC,CAAC;AAEH,oGAAoG;AACpG,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;IAC3C,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,MAAM,CAAY,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AACH,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;IACzC,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;;;;;;;GAQG;AACH,SAAS,QAAQ,CAAC,OAA0B;IAC1C,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAClC,MAAM,IAAI,GAA8C,EAAE,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,aAAa,GAAG,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC3E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACpD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,SAAS;YAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;gBACpC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,eAAe,EAAE,CAAC;gBACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;YAC9E,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChE,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;gBAClF,MAAM;aACP,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AAC3C,CAAC;AAED,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,OAA0B,EAAE,EAAE;IACzD,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC"}
@@ -8,7 +8,7 @@ import type { Context } from '@cyanheads/mcp-ts-core';
8
8
  import { type Dispatcher, type RequestInit, fetch as undiciFetch } from 'undici';
9
9
  import { type ServerConfig } from '../../config/server-config.js';
10
10
  import { PathPolicy } from './path-policy.js';
11
- import type { DocumentMap, FileListing, NoteJson, NoteTarget, ObsidianCommand, ObsidianTag, OmnisearchHit, PatchInstruction, StructuredSearchHit, TextSearchHit, VaultStatus } from './types.js';
11
+ import type { DocumentMap, FileListing, NoteJson, NoteTarget, ObsidianCommand, ObsidianTag, OmnisearchHit, PatchInstruction, PathTarget, StructuredSearchHit, TextSearchHit, VaultStatus } from './types.js';
12
12
  type UndiciResponse = Awaited<ReturnType<typeof undiciFetch>>;
13
13
  /**
14
14
  * The HTTP fetch contract this service depends on. Defaults to undici's
@@ -35,7 +35,7 @@ export declare class ObsidianService {
35
35
  * `fetch`, which honors the constructed TLS dispatcher in production.
36
36
  */
37
37
  constructor(config: ServerConfig, fetchImpl?: ObsidianFetch);
38
- /** Path-policy accessor — used by `obsidian_search_notes` to filter hits. */
38
+ /** Path-policy accessor for tools that filter results or check scope themselves. */
39
39
  get policy(): PathPolicy;
40
40
  /** Resolved Omnisearch URL (derived from baseUrl or OBSIDIAN_OMNISEARCH_URL override). */
41
41
  get omnisearchUrl(): string;
@@ -64,11 +64,27 @@ export declare class ObsidianService {
64
64
  getNoteContent(ctx: Context, target: NoteTarget): Promise<string>;
65
65
  getNoteJson(ctx: Context, target: NoteTarget): Promise<NoteJson>;
66
66
  /**
67
- * Resolve `target` to a vault-relative path. For path targets this is a
68
- * no-op; for `active` and `periodic` targets we have to ask upstream which
69
- * concrete file is currently in play.
67
+ * Pin `target` to the note it names right now. A path target comes back as
68
+ * sent; an `active` or `periodic` target is resolved upstream (read-gated)
69
+ * and comes back as a path target for that note, so every later call acts on
70
+ * the same file however the target moves in between.
71
+ */
72
+ resolveTarget(ctx: Context, target: NoteTarget): Promise<PathTarget>;
73
+ /**
74
+ * `target` as a path target for `path`, the note a read of `target` returned.
75
+ * A path target already names its note and comes back as sent. A pinned
76
+ * `active` / `periodic` target carries the target's label as `resolvedFrom`,
77
+ * the identifier `no_active_file` and `periodic_not_found` use, so a
78
+ * `path_forbidden` denial on it names the target rather than the note.
79
+ */
80
+ pinTarget(target: NoteTarget, path: string): PathTarget;
81
+ /**
82
+ * The note's headings, block ids, and frontmatter field names. An `active` /
83
+ * `periodic` target is resolved once (read-gated, a denial named by the
84
+ * target's label) and the map read from the resolved `/vault/` path, which
85
+ * the plugin's `/active/` and `/periodic/…` routes delegate to anyway, so the
86
+ * map describes the note the resolution returned even if the target moves.
70
87
  */
71
- resolvePath(ctx: Context, target: NoteTarget): Promise<string>;
72
88
  getDocumentMap(ctx: Context, target: NoteTarget): Promise<DocumentMap>;
73
89
  writeNote(ctx: Context, target: NoteTarget, content: string, contentType?: 'markdown' | 'json'): Promise<void>;
74
90
  appendToNote(ctx: Context, target: NoteTarget, content: string, contentType?: 'markdown' | 'json'): Promise<void>;
@@ -109,8 +125,8 @@ export declare class ObsidianService {
109
125
  /**
110
126
  * Vault tags with usage counts, hierarchical parents included. Unscoped, the
111
127
  * plugin's `/tags/` with its occurrence counts. That payload carries no
112
- * per-note attribution, so under OBSIDIAN_READ_PATHS the tags are collected
113
- * per note with one JsonLogic search instead, kept to readable notes, and
128
+ * per-note attribution, so under OBSIDIAN_READ_PATHS the tags are read from
129
+ * the readable notes' contexts instead (one upstream search, no bodies), and
114
130
  * each one counts the readable notes carrying it or a tag nested under it.
115
131
  */
116
132
  listTags(ctx: Context): Promise<ObsidianTag[]>;
@@ -127,7 +143,39 @@ export declare class ObsidianService {
127
143
  * failure.
128
144
  */
129
145
  searchText(ctx: Context, query: string, contextLength?: number): Promise<TextSearchHit[]>;
146
+ /**
147
+ * JSONLogic search. Unscoped, the tree goes to the plugin unchanged. Under
148
+ * OBSIDIAN_READ_PATHS the plugin would evaluate it against every note in
149
+ * the vault, so the tree stays here instead: the readable notes' contexts
150
+ * are fetched and the tree is evaluated over those alone
151
+ * (`createJsonLogicEvaluation`), the way the plugin evaluates it. No hit,
152
+ * result, or error then reads a note outside the read scope; which note a
153
+ * link resolves to is still Obsidian's vault-wide resolution, so `links`,
154
+ * `backlinks`, and `unresolvedLinks` can change when a note outside the
155
+ * scope is created or removed.
156
+ *
157
+ * The plugin hands a tree note bodies only when its JSON holds the string
158
+ * `"content"` (`readsContent`); such a tree gets them here too, fetched
159
+ * and evaluated in batches of at most `CONTENT_BATCH_BYTES` so a broad
160
+ * scope never holds every readable body at once.
161
+ */
130
162
  searchJsonLogic(ctx: Context, logic: Record<string, unknown>): Promise<StructuredSearchHit[]>;
163
+ /**
164
+ * A JSONLogic search for a caller paging through its hits `pageSize` at a
165
+ * time. Unscoped, it is `searchJsonLogic`. Under OBSIDIAN_READ_PATHS a call
166
+ * without `walk` evaluates fresh and, when the hits run past one page,
167
+ * stores the full ordered hit list under a new walk id, returned as `walk`;
168
+ * a call naming that id with the same tree is served from the stored list
169
+ * without evaluating. The store belongs to this service, whose read scope
170
+ * is fixed at construction, so a list is only read under the scope that
171
+ * produced it. Anything else — an expired, evicted, or unknown id, or a
172
+ * different tree — evaluates fresh, and a call cancelled before it answers
173
+ * stores nothing.
174
+ */
175
+ pageJsonLogic(ctx: Context, logic: Record<string, unknown>, walk: string | undefined, pageSize: number): Promise<{
176
+ hits: StructuredSearchHit[];
177
+ walk?: string;
178
+ }>;
131
179
  /**
132
180
  * One-shot startup probe for the Omnisearch plugin's HTTP endpoint. Returns
133
181
  * `true` only when the response is `HTTP 200`, declares `application/json`,
@@ -1 +1 @@
1
- {"version":3,"file":"obsidian-service.d.ts","sourceRoot":"","sources":["../../../src/services/obsidian/obsidian-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"obsidian-service.d.ts","sourceRoot":"","sources":["../../../src/services/obsidian/obsidian-service.ts"],"names":[],"mappings":"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"}