@batalabs/virlow-mcp-core 3.11.4 → 3.11.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.
Files changed (42) hide show
  1. package/dist/cjs/api.d.ts +117 -0
  2. package/dist/cjs/api.js +113 -0
  3. package/dist/cjs/embedding-cache.d.ts +33 -0
  4. package/dist/cjs/embedding-cache.js +114 -0
  5. package/dist/cjs/exposure.d.ts +41 -0
  6. package/dist/cjs/exposure.js +77 -0
  7. package/dist/cjs/index.d.ts +15 -0
  8. package/dist/cjs/index.js +32 -0
  9. package/dist/cjs/memories-enabled.d.ts +15 -0
  10. package/dist/cjs/memories-enabled.js +32 -0
  11. package/dist/cjs/memories.d.ts +85 -0
  12. package/dist/cjs/memories.js +353 -0
  13. package/dist/cjs/memory-note.d.ts +44 -0
  14. package/dist/cjs/memory-note.js +149 -0
  15. package/dist/cjs/memory-tree.d.ts +27 -0
  16. package/dist/cjs/memory-tree.js +72 -0
  17. package/dist/cjs/notes.d.ts +108 -0
  18. package/dist/cjs/notes.js +237 -0
  19. package/dist/cjs/package.json +1 -0
  20. package/dist/cjs/vault.d.ts +34 -0
  21. package/dist/cjs/vault.js +77 -0
  22. package/dist/exposure.d.ts +1 -1
  23. package/dist/exposure.d.ts.map +1 -1
  24. package/dist/index.d.ts +15 -15
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +9 -9
  27. package/dist/index.js.map +1 -1
  28. package/dist/memories-enabled.d.ts +1 -1
  29. package/dist/memories-enabled.d.ts.map +1 -1
  30. package/dist/memories.d.ts +4 -4
  31. package/dist/memories.d.ts.map +1 -1
  32. package/dist/memories.js +3 -3
  33. package/dist/memories.js.map +1 -1
  34. package/dist/memory-tree.d.ts +1 -1
  35. package/dist/memory-tree.d.ts.map +1 -1
  36. package/dist/memory-tree.js +1 -1
  37. package/dist/memory-tree.js.map +1 -1
  38. package/dist/notes.d.ts +3 -3
  39. package/dist/notes.d.ts.map +1 -1
  40. package/dist/notes.js +1 -1
  41. package/dist/notes.js.map +1 -1
  42. package/package.json +13 -7
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MEMORIES_ROOT_NAME = void 0;
4
+ exports.resolveMemoryTree = resolveMemoryTree;
5
+ exports.ensureNamespace = ensureNamespace;
6
+ const api_js_1 = require("./api.js");
7
+ /** Name given to the memories root when the server has to create it. The root
8
+ * is identified by `kind`, never by this name — the user is free to rename it. */
9
+ exports.MEMORIES_ROOT_NAME = 'Memories';
10
+ function buildTree(rootId, folders) {
11
+ const namespaces = new Map();
12
+ const byFolderId = new Map();
13
+ const attach = (folderId, name) => {
14
+ byFolderId.set(folderId, name);
15
+ // Two subfolders may share a name — that is the user's organising choice.
16
+ // Both count as that namespace; writes go to the first.
17
+ if (!namespaces.has(name))
18
+ namespaces.set(name, folderId);
19
+ };
20
+ // Only direct children of the root are namespaces. Anything deeper is an
21
+ // ordinary folder the user nested for their own reasons; its notes are not
22
+ // memories, so it never reaches byFolderId and the sync walk skips it.
23
+ for (const folder of folders) {
24
+ if (folder.parentId === rootId)
25
+ attach(folder.id, folder.name);
26
+ }
27
+ return {
28
+ rootId,
29
+ namespaces,
30
+ namespaceOf: (folderId) => byFolderId.get(folderId),
31
+ folderIds: () => [rootId, ...byFolderId.keys()],
32
+ attach,
33
+ };
34
+ }
35
+ /**
36
+ * Resolve the memories folder tree, creating the root if the user has none.
37
+ * The root is whichever folder carries `kind: 'memories'` — the API allows
38
+ * only one per user.
39
+ */
40
+ async function resolveMemoryTree(api) {
41
+ const { folders } = await api.listFolders();
42
+ const existing = folders.find((f) => f.kind === 'memories');
43
+ if (existing)
44
+ return buildTree(existing.id, folders);
45
+ try {
46
+ const created = await api.createFolder(exports.MEMORIES_ROOT_NAME, null, 'memories');
47
+ return buildTree(created.id, [...folders, created]);
48
+ }
49
+ catch (err) {
50
+ // 409 MEMORIES_FOLDER_EXISTS: another client created the root between our
51
+ // listing and our POST. Re-list and use the winner.
52
+ if (!(err instanceof api_js_1.ApiError) || err.status !== 409)
53
+ throw err;
54
+ const retry = await api.listFolders();
55
+ const winner = retry.folders.find((f) => f.kind === 'memories');
56
+ if (!winner)
57
+ throw err;
58
+ return buildTree(winner.id, retry.folders);
59
+ }
60
+ }
61
+ /**
62
+ * Folder id for `name`, creating the namespace subfolder if it does not exist
63
+ * yet. Mutates `tree` so a later call in the same session is a cache hit.
64
+ */
65
+ async function ensureNamespace(api, tree, name) {
66
+ const existing = tree.namespaces.get(name);
67
+ if (existing)
68
+ return existing;
69
+ const created = await api.createFolder(name, tree.rootId);
70
+ tree.attach(created.id, name);
71
+ return created.id;
72
+ }
@@ -0,0 +1,108 @@
1
+ import { type Exposure } from './exposure.js';
2
+ import type { VirlowApi } from './api.js';
3
+ import type { Vault } from './vault.js';
4
+ /** Hard ceiling on how many notes searchNotes() will decrypt+scan in a
5
+ * single call. Keeps a single search bounded even for very large accounts;
6
+ * `truncated` tells the caller when the account holds more than this. */
7
+ export declare const SEARCH_SCAN_CAP = 500;
8
+ export declare class NotesService {
9
+ private readonly api;
10
+ private readonly vault;
11
+ /** Per-unlock cache of decrypted (title, content) keyed by `id:updatedAt`
12
+ * so re-reading/re-scanning the same note twice in one unlock doesn't
13
+ * re-run AES-GCM decryption. Cleared whenever the vault locks. */
14
+ private readonly decryptCache;
15
+ /** Bumped every time the vault locks (see handleLock()). decryptRow()
16
+ * captures this before its await on decryptNoteFields() and re-checks it
17
+ * afterward, so a decrypt that was still in flight when the vault locked
18
+ * never writes decrypted plaintext into the cache after the lock. */
19
+ private epoch;
20
+ /** Serializes updateNote() calls so two overlapping partial edits to the
21
+ * same note (e.g. one changing title, one changing content) never race
22
+ * their read-merge-encrypt-write cycle — without this, both could read
23
+ * the same pre-edit row and the second write would silently clobber the
24
+ * first's change. Mirrors MemoryStore's enqueue()/mutationChain pattern. */
25
+ private mutationChain;
26
+ constructor(api: VirlowApi, vault: Vault);
27
+ private handleLock;
28
+ listNotes(params: {
29
+ folderId?: string;
30
+ starred?: boolean;
31
+ archived?: boolean;
32
+ page?: number;
33
+ limit?: number;
34
+ }): Promise<{
35
+ notes: Array<{
36
+ id: string;
37
+ title: string;
38
+ folderId: string | null;
39
+ starred: boolean;
40
+ updatedAt: string;
41
+ }>;
42
+ pagination: {
43
+ page: number;
44
+ limit: number;
45
+ total: number;
46
+ pages: number;
47
+ };
48
+ /** How many otherwise-visible notes were withheld, split by why — the
49
+ * remedy differs. Reported so a filtered list can never be mistaken for an
50
+ * empty one. */
51
+ withheld: {
52
+ inClosedFolders: number;
53
+ unfiled: number;
54
+ };
55
+ exposure: Exposure;
56
+ }>;
57
+ readNote(id: string): Promise<{
58
+ id: string;
59
+ title: string;
60
+ content: string;
61
+ folderId: string | null;
62
+ }>;
63
+ createNote(title: string, content: string, folderId?: string | null, type?: string): Promise<{
64
+ id: string;
65
+ }>;
66
+ updateNote(id: string, changes: {
67
+ title?: string;
68
+ content?: string;
69
+ }): Promise<void>;
70
+ searchNotes(query: string, limit?: number): Promise<{
71
+ results: Array<{
72
+ id: string;
73
+ title: string;
74
+ snippet: string;
75
+ }>;
76
+ scanned: number;
77
+ truncated: boolean;
78
+ }>;
79
+ moveNote(id: string, folderId: string | null): Promise<void>;
80
+ setStar(id: string, starred: boolean): Promise<void>;
81
+ archiveNote(id: string, archived: boolean): Promise<void>;
82
+ trashNote(id: string): Promise<void>;
83
+ listFolders(): Promise<{
84
+ folders: Array<{
85
+ id: string;
86
+ name: string;
87
+ parentId: string | null;
88
+ }>;
89
+ withheld: number;
90
+ }>;
91
+ /** Folder exposure for this request. Not cached across calls: the user can
92
+ * flip the switch in the app at any moment and the next tool call must
93
+ * respect it. */
94
+ private exposure;
95
+ createFolder(name: string, parentId?: string | null): Promise<{
96
+ id: string;
97
+ }>;
98
+ /** Decrypt (with per-unlock caching) or pass through a legacy plaintext
99
+ * row. Legacy rows (no encryptedTitle) carry their real content directly
100
+ * in the plaintext title/content columns. */
101
+ private decryptRow;
102
+ private buildSnippet;
103
+ private requireSession;
104
+ /** Chains `fn` onto the mutation queue so overlapping calls run one at a
105
+ * time; the `.catch(() => {})` guard keeps the internal chain alive after
106
+ * a rejection while the promise returned to the caller still carries it. */
107
+ private enqueue;
108
+ }
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotesService = exports.SEARCH_SCAN_CAP = void 0;
4
+ const virlow_crypto_1 = require("@batalabs/virlow-crypto");
5
+ const exposure_js_1 = require("./exposure.js");
6
+ /** Hard ceiling on how many notes searchNotes() will decrypt+scan in a
7
+ * single call. Keeps a single search bounded even for very large accounts;
8
+ * `truncated` tells the caller when the account holds more than this. */
9
+ exports.SEARCH_SCAN_CAP = 500;
10
+ const SEARCH_PAGE_LIMIT = 50;
11
+ /** Window radius (chars) either side of the match start when building a
12
+ * content snippet; total window is up to 2*SNIPPET_RADIUS. */
13
+ const SNIPPET_RADIUS = 80;
14
+ class NotesService {
15
+ api;
16
+ vault;
17
+ /** Per-unlock cache of decrypted (title, content) keyed by `id:updatedAt`
18
+ * so re-reading/re-scanning the same note twice in one unlock doesn't
19
+ * re-run AES-GCM decryption. Cleared whenever the vault locks. */
20
+ decryptCache = new Map();
21
+ /** Bumped every time the vault locks (see handleLock()). decryptRow()
22
+ * captures this before its await on decryptNoteFields() and re-checks it
23
+ * afterward, so a decrypt that was still in flight when the vault locked
24
+ * never writes decrypted plaintext into the cache after the lock. */
25
+ epoch = 0;
26
+ /** Serializes updateNote() calls so two overlapping partial edits to the
27
+ * same note (e.g. one changing title, one changing content) never race
28
+ * their read-merge-encrypt-write cycle — without this, both could read
29
+ * the same pre-edit row and the second write would silently clobber the
30
+ * first's change. Mirrors MemoryStore's enqueue()/mutationChain pattern. */
31
+ mutationChain = Promise.resolve();
32
+ constructor(api, vault) {
33
+ this.api = api;
34
+ this.vault = vault;
35
+ this.vault.onLock = () => this.handleLock();
36
+ }
37
+ handleLock() {
38
+ this.decryptCache.clear();
39
+ this.epoch++;
40
+ }
41
+ async listNotes(params) {
42
+ const key = this.requireSession();
43
+ const { notes, pagination } = await this.api.listNotes({ ...params, deleted: false });
44
+ // Hidden notes are segregated client-side by the web app (see ApiNote's
45
+ // `hidden` doc comment); the MCP server mirrors that here so they never
46
+ // surface in list/search results. readNote() still allows fetching one
47
+ // by exact id — that's a deliberate, explicit request.
48
+ const exposure = await this.exposure();
49
+ const notHidden = notes.filter((row) => row.hidden !== true);
50
+ // Folders the user has not opened to AI tools are filtered here rather
51
+ // than at the API, so the count of what was withheld can be reported.
52
+ const visible = notHidden.filter((row) => exposure.allows(row.folderId));
53
+ const withheld = {
54
+ inClosedFolders: notHidden.filter((row) => row.folderId !== null && !exposure.allows(row.folderId)).length,
55
+ unfiled: notHidden.filter((row) => row.folderId === null).length,
56
+ };
57
+ const mapped = await Promise.all(visible.map(async (row) => {
58
+ const { title } = await this.decryptRow(key, row);
59
+ return {
60
+ id: row.id,
61
+ title,
62
+ folderId: row.folderId,
63
+ starred: row.starred === true,
64
+ updatedAt: row.updatedAt,
65
+ };
66
+ }));
67
+ return { notes: mapped, pagination, withheld, exposure };
68
+ }
69
+ async readNote(id) {
70
+ const key = this.requireSession();
71
+ const row = await this.api.getNote(id);
72
+ // Reading by exact id is still a read: the switch says the assistant may
73
+ // not read this folder, and knowing the id does not change that.
74
+ const exposure = await this.exposure();
75
+ if (!exposure.allows(row.folderId)) {
76
+ throw new Error(`Note ${id} is in a folder that is not exposed to MCP. Turn on "Expose to MCP" in that folder's settings in the Virlow app to read it here.`);
77
+ }
78
+ const { title, content } = await this.decryptRow(key, row);
79
+ return { id: row.id, title, content, folderId: row.folderId };
80
+ }
81
+ async createNote(title, content, folderId, type) {
82
+ const key = this.requireSession();
83
+ const salt = (0, virlow_crypto_1.bytesToBase64)(crypto.getRandomValues(new Uint8Array(32)));
84
+ const { encryptedTitle, encryptedContent, iv } = await (0, virlow_crypto_1.encryptNoteFields)(key, title, content);
85
+ const body = {
86
+ title: '[ENCRYPTED]',
87
+ content: '[ENCRYPTED]',
88
+ encryptedTitle,
89
+ encryptedContent,
90
+ iv,
91
+ salt,
92
+ };
93
+ if (folderId !== undefined)
94
+ body.folderId = folderId;
95
+ if (type !== undefined)
96
+ body.type = type;
97
+ const row = await this.api.createNote(body);
98
+ return { id: row.id };
99
+ }
100
+ updateNote(id, changes) {
101
+ return this.enqueue(async () => {
102
+ const key = this.requireSession();
103
+ const existingRow = await this.api.getNote(id);
104
+ const current = await this.decryptRow(key, existingRow);
105
+ const title = changes.title ?? current.title;
106
+ const content = changes.content ?? current.content;
107
+ const salt = (0, virlow_crypto_1.bytesToBase64)(crypto.getRandomValues(new Uint8Array(32)));
108
+ const { encryptedTitle, encryptedContent, iv } = await (0, virlow_crypto_1.encryptNoteFields)(key, title, content);
109
+ await this.api.updateNote(id, {
110
+ title: '[ENCRYPTED]',
111
+ content: '[ENCRYPTED]',
112
+ encryptedTitle,
113
+ encryptedContent,
114
+ iv,
115
+ salt,
116
+ });
117
+ });
118
+ }
119
+ async searchNotes(query, limit = 20) {
120
+ const key = this.requireSession();
121
+ const q = query.toLowerCase();
122
+ const results = [];
123
+ let scanned = 0;
124
+ let total = 0;
125
+ let page = 1;
126
+ scan: for (;;) {
127
+ const { notes, pagination } = await this.api.listNotes({ page, limit: SEARCH_PAGE_LIMIT, deleted: false });
128
+ total = pagination.total;
129
+ for (const row of notes) {
130
+ if (row.hidden === true)
131
+ continue;
132
+ if (scanned >= exports.SEARCH_SCAN_CAP)
133
+ break scan;
134
+ scanned++;
135
+ const { title, content } = await this.decryptRow(key, row);
136
+ const contentIdx = content.toLowerCase().indexOf(q);
137
+ const titleMatch = title.toLowerCase().includes(q);
138
+ if (titleMatch || contentIdx !== -1) {
139
+ results.push({ id: row.id, title, snippet: this.buildSnippet(title, content, contentIdx) });
140
+ }
141
+ }
142
+ if (scanned >= exports.SEARCH_SCAN_CAP)
143
+ break;
144
+ if (notes.length === 0 || page >= pagination.pages)
145
+ break;
146
+ page++;
147
+ }
148
+ return { results: results.slice(0, limit), scanned, truncated: total > exports.SEARCH_SCAN_CAP };
149
+ }
150
+ async moveNote(id, folderId) {
151
+ this.requireSession();
152
+ await this.api.updateNote(id, { folderId });
153
+ }
154
+ async setStar(id, starred) {
155
+ this.requireSession();
156
+ await this.api.updateNote(id, { starred });
157
+ }
158
+ async archiveNote(id, archived) {
159
+ this.requireSession();
160
+ await this.api.updateNote(id, { archived });
161
+ }
162
+ async trashNote(id) {
163
+ this.requireSession();
164
+ await this.api.updateNote(id, { deleted: true });
165
+ }
166
+ async listFolders() {
167
+ this.requireSession();
168
+ const { folders } = await this.api.listFolders();
169
+ const exposure = (0, exposure_js_1.computeExposure)(folders);
170
+ const visible = folders.filter((f) => exposure.allows(f.id));
171
+ return {
172
+ // Names are withheld along with contents: a folder the user has not
173
+ // opened should not be inventoried either, only counted.
174
+ folders: visible.map((f) => ({ id: f.id, name: f.name, parentId: f.parentId })),
175
+ withheld: folders.length - visible.length,
176
+ };
177
+ }
178
+ /** Folder exposure for this request. Not cached across calls: the user can
179
+ * flip the switch in the app at any moment and the next tool call must
180
+ * respect it. */
181
+ async exposure() {
182
+ const { folders } = await this.api.listFolders();
183
+ return (0, exposure_js_1.computeExposure)(folders);
184
+ }
185
+ async createFolder(name, parentId) {
186
+ this.requireSession();
187
+ const folder = await this.api.createFolder(name, parentId);
188
+ return { id: folder.id };
189
+ }
190
+ /** Decrypt (with per-unlock caching) or pass through a legacy plaintext
191
+ * row. Legacy rows (no encryptedTitle) carry their real content directly
192
+ * in the plaintext title/content columns. */
193
+ async decryptRow(key, row) {
194
+ if (!row.encryptedTitle) {
195
+ return { title: row.title, content: row.content };
196
+ }
197
+ const cacheKey = `${row.id}:${row.updatedAt}`;
198
+ const cached = this.decryptCache.get(cacheKey);
199
+ if (cached)
200
+ return cached;
201
+ const startEpoch = this.epoch;
202
+ const fields = await (0, virlow_crypto_1.decryptNoteFields)(key, row.encryptedTitle, row.encryptedContent ?? '', row.iv ?? '');
203
+ // If the vault locked while this decrypt was in flight, the epoch moved
204
+ // on and decryptCache was already cleared — don't write plaintext back
205
+ // into it after the fact.
206
+ if (this.epoch === startEpoch) {
207
+ this.decryptCache.set(cacheKey, fields);
208
+ }
209
+ return fields;
210
+ }
211
+ buildSnippet(title, content, contentMatchIndex) {
212
+ if (contentMatchIndex === -1) {
213
+ return title;
214
+ }
215
+ const windowSize = SNIPPET_RADIUS * 2;
216
+ let start = Math.max(0, contentMatchIndex - SNIPPET_RADIUS);
217
+ const end = Math.min(content.length, start + windowSize);
218
+ if (end - start < windowSize) {
219
+ start = Math.max(0, end - windowSize);
220
+ }
221
+ return content.slice(start, end);
222
+ }
223
+ requireSession() {
224
+ const key = this.vault.session.key;
225
+ this.vault.touch();
226
+ return key;
227
+ }
228
+ /** Chains `fn` onto the mutation queue so overlapping calls run one at a
229
+ * time; the `.catch(() => {})` guard keeps the internal chain alive after
230
+ * a rejection while the promise returned to the caller still carries it. */
231
+ enqueue(fn) {
232
+ const next = this.mutationChain.then(fn, fn);
233
+ this.mutationChain = next.catch(() => { });
234
+ return next;
235
+ }
236
+ }
237
+ exports.NotesService = NotesService;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,34 @@
1
+ export declare class LockedError extends Error {
2
+ }
3
+ export interface UnlockedSession {
4
+ key: CryptoKey;
5
+ userId: string;
6
+ email: string;
7
+ }
8
+ export declare class Vault {
9
+ private readonly autoLockMs;
10
+ private _session;
11
+ private _timerHandle;
12
+ /** Listeners registered via `onLock =` or `addLockListener()`. Multiple
13
+ * consumers (MemoryStore, NotesService, ...) each need their cache cleared
14
+ * on lock; a single-slot callback would let the second registration
15
+ * silently clobber the first. */
16
+ private lockListeners;
17
+ constructor(autoLockMs?: number);
18
+ /** Alias for `addLockListener` kept for call-site brevity (`vault.onLock = fn`).
19
+ * Assigning multiple times ADDS a listener each time — it does not replace
20
+ * a previous one. */
21
+ set onLock(fn: () => void);
22
+ addLockListener(fn: () => void): void;
23
+ setUnlocked(session: UnlockedSession): void;
24
+ lock(): void;
25
+ isUnlocked(): boolean;
26
+ status(): {
27
+ locked: boolean;
28
+ email?: string;
29
+ };
30
+ touch(): void;
31
+ get session(): UnlockedSession;
32
+ private _scheduleAutoLock;
33
+ private _clearTimer;
34
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Vault = exports.LockedError = void 0;
4
+ class LockedError extends Error {
5
+ }
6
+ exports.LockedError = LockedError;
7
+ class Vault {
8
+ autoLockMs;
9
+ _session = null;
10
+ _timerHandle = null;
11
+ /** Listeners registered via `onLock =` or `addLockListener()`. Multiple
12
+ * consumers (MemoryStore, NotesService, ...) each need their cache cleared
13
+ * on lock; a single-slot callback would let the second registration
14
+ * silently clobber the first. */
15
+ lockListeners = [];
16
+ constructor(autoLockMs = 4 * 60 * 60 * 1000) {
17
+ this.autoLockMs = autoLockMs;
18
+ }
19
+ /** Alias for `addLockListener` kept for call-site brevity (`vault.onLock = fn`).
20
+ * Assigning multiple times ADDS a listener each time — it does not replace
21
+ * a previous one. */
22
+ set onLock(fn) {
23
+ this.addLockListener(fn);
24
+ }
25
+ addLockListener(fn) {
26
+ this.lockListeners.push(fn);
27
+ }
28
+ setUnlocked(session) {
29
+ this._session = session;
30
+ this._scheduleAutoLock();
31
+ }
32
+ lock() {
33
+ if (this._session === null) {
34
+ return; // Already locked, idempotent
35
+ }
36
+ this._clearTimer();
37
+ this._session = null;
38
+ for (const listener of this.lockListeners) {
39
+ listener();
40
+ }
41
+ }
42
+ isUnlocked() {
43
+ return this._session !== null;
44
+ }
45
+ status() {
46
+ if (this._session === null) {
47
+ return { locked: true };
48
+ }
49
+ return { locked: false, email: this._session.email };
50
+ }
51
+ touch() {
52
+ if (this._session === null) {
53
+ return; // Already locked, ignore
54
+ }
55
+ this._clearTimer();
56
+ this._scheduleAutoLock();
57
+ }
58
+ get session() {
59
+ if (this._session === null) {
60
+ throw new LockedError('Vault is locked. Ask the user to run the unlock tool to sign in and unlock their Virlow vault.');
61
+ }
62
+ return this._session;
63
+ }
64
+ _scheduleAutoLock() {
65
+ this._timerHandle = setTimeout(() => {
66
+ this.lock();
67
+ }, this.autoLockMs);
68
+ this._timerHandle.unref?.();
69
+ }
70
+ _clearTimer() {
71
+ if (this._timerHandle !== null) {
72
+ clearTimeout(this._timerHandle);
73
+ this._timerHandle = null;
74
+ }
75
+ }
76
+ }
77
+ exports.Vault = Vault;
@@ -1,4 +1,4 @@
1
- import type { ApiFolder } from './api';
1
+ import type { ApiFolder } from './api.js';
2
2
  /**
3
3
  * Which folders the user has actually opened to AI tools.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"exposure.d.ts","sourceRoot":"","sources":["../src/exposure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,iDAAiD;IACjD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;IACzC,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;oBAEgB;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B;;;0EAGsE;IACtE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,EACjC,IAAI,GAAE,eAAoB,GACzB,QAAQ,CAgDV;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACpD,QAAQ,EAAE,QAAQ,GACjB,MAAM,CA6BR"}
1
+ {"version":3,"file":"exposure.d.ts","sourceRoot":"","sources":["../src/exposure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,iDAAiD;IACjD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;IACzC,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;oBAEgB;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B;;;0EAGsE;IACtE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,EACjC,IAAI,GAAE,eAAoB,GACzB,QAAQ,CAgDV;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACpD,QAAQ,EAAE,QAAQ,GACjB,MAAM,CA6BR"}
package/dist/index.d.ts CHANGED
@@ -1,16 +1,16 @@
1
- export { ApiError, VirlowApi } from './api';
2
- export type { ApiFolder, ApiNote, AuthTokens, LoginResult, NoteWrite } from './api';
3
- export { LockedError, Vault } from './vault';
4
- export type { UnlockedSession } from './vault';
5
- export { NotesService, SEARCH_SCAN_CAP } from './notes';
6
- export { MemoryStore, SYNC_PAGE_LIMIT } from './memories';
7
- export type { CachedMemory, SimilarMemory, SyncResult } from './memories';
8
- export { mergeMeta, parseMemoryNote, serializeMemoryBody, toCodeEnvelope, } from './memory-note';
9
- export type { MemoryMeta, ParsedMemoryNote } from './memory-note';
10
- export { MEMORIES_ROOT_NAME, ensureNamespace, resolveMemoryTree, } from './memory-tree';
11
- export type { MemoryTree } from './memory-tree';
12
- export { computeExposure, filteredNotice } from './exposure';
13
- export type { Exposure } from './exposure';
14
- export { EmbeddingCache } from './embedding-cache';
15
- export { MEMORIES_DISABLED_MESSAGE, memoriesAllowed } from './memories-enabled';
1
+ export { ApiError, VirlowApi } from './api.js';
2
+ export type { ApiFolder, ApiNote, AuthTokens, LoginResult, NoteWrite } from './api.js';
3
+ export { LockedError, Vault } from './vault.js';
4
+ export type { UnlockedSession } from './vault.js';
5
+ export { NotesService, SEARCH_SCAN_CAP } from './notes.js';
6
+ export { MemoryStore, SYNC_PAGE_LIMIT } from './memories.js';
7
+ export type { CachedMemory, SimilarMemory, SyncResult } from './memories.js';
8
+ export { mergeMeta, parseMemoryNote, serializeMemoryBody, toCodeEnvelope, } from './memory-note.js';
9
+ export type { MemoryMeta, ParsedMemoryNote } from './memory-note.js';
10
+ export { MEMORIES_ROOT_NAME, ensureNamespace, resolveMemoryTree, } from './memory-tree.js';
11
+ export type { MemoryTree } from './memory-tree.js';
12
+ export { computeExposure, filteredNotice } from './exposure.js';
13
+ export type { Exposure } from './exposure.js';
14
+ export { EmbeddingCache } from './embedding-cache.js';
15
+ export { MEMORIES_DISABLED_MESSAGE, memoriesAllowed } from './memories-enabled.js';
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAChE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- export { ApiError, VirlowApi } from './api';
2
- export { LockedError, Vault } from './vault';
3
- export { NotesService, SEARCH_SCAN_CAP } from './notes';
4
- export { MemoryStore, SYNC_PAGE_LIMIT } from './memories';
5
- export { mergeMeta, parseMemoryNote, serializeMemoryBody, toCodeEnvelope, } from './memory-note';
6
- export { MEMORIES_ROOT_NAME, ensureNamespace, resolveMemoryTree, } from './memory-tree';
7
- export { computeExposure, filteredNotice } from './exposure';
8
- export { EmbeddingCache } from './embedding-cache';
9
- export { MEMORIES_DISABLED_MESSAGE, memoriesAllowed } from './memories-enabled';
1
+ export { ApiError, VirlowApi } from './api.js';
2
+ export { LockedError, Vault } from './vault.js';
3
+ export { NotesService, SEARCH_SCAN_CAP } from './notes.js';
4
+ export { MemoryStore, SYNC_PAGE_LIMIT } from './memories.js';
5
+ export { mergeMeta, parseMemoryNote, serializeMemoryBody, toCodeEnvelope, } from './memory-note.js';
6
+ export { MEMORIES_ROOT_NAME, ensureNamespace, resolveMemoryTree, } from './memory-tree.js';
7
+ export { computeExposure, filteredNotice } from './exposure.js';
8
+ export { EmbeddingCache } from './embedding-cache.js';
9
+ export { MEMORIES_DISABLED_MESSAGE, memoriesAllowed } from './memories-enabled.js';
10
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { VirlowApi } from './api';
1
+ import type { VirlowApi } from './api.js';
2
2
  /**
3
3
  * Whether the user has switched AI memories on, read fresh from the account.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"memories-enabled.d.ts","sourceRoot":"","sources":["../src/memories-enabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAYtE;AAED,eAAO,MAAM,yBAAyB,QAEqB,CAAC"}
1
+ {"version":3,"file":"memories-enabled.d.ts","sourceRoot":"","sources":["../src/memories-enabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAYtE;AAED,eAAO,MAAM,yBAAyB,QAEqB,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import { type Embedder } from '@batalabs/virlow-memory';
2
- import { type VirlowApi } from './api';
3
- import type { EmbeddingCache } from './embedding-cache';
4
- import { type MemoryMeta } from './memory-note';
5
- import type { Vault } from './vault';
2
+ import { type VirlowApi } from './api.js';
3
+ import type { EmbeddingCache } from './embedding-cache.js';
4
+ import { type MemoryMeta } from './memory-note.js';
5
+ import type { Vault } from './vault.js';
6
6
  export declare const SYNC_PAGE_LIMIT = 100;
7
7
  export interface CachedMemory {
8
8
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../src/memories.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../src/memories.ts"],"names":[],"mappings":"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"}