@mnemonik/scanner 1.0.0 → 2.0.1

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/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # @mnemonik/scanner
2
+
3
+ Automatic codebase indexing daemon for [Mnemonik](https://mnemonik.dev) — persistent memory for AI coding assistants.
4
+
5
+ The scanner watches your project directories for code changes and indexes them so your AI assistant can find relevant files, functions, and patterns when you need them.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g @mnemonik/scanner
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ mnemonik-scanner start --key <your-api-key> --roots ~/Projects
17
+ ```
18
+
19
+ Your API key is available on the [Mnemonik dashboard](https://app.mnemonik.dev). The `--roots` flag specifies which directories to scan for projects (comma-separated).
20
+
21
+ Configuration is saved to `~/.mnemonik/scanner.json` after first run. Subsequent starts need no arguments:
22
+
23
+ ```bash
24
+ mnemonik-scanner start
25
+ ```
26
+
27
+ ## How It Works
28
+
29
+ 1. The daemon walks your `--roots` directories looking for `.mnemonik.json` files (created automatically by your IDE's Mnemonik integration)
30
+ 2. For each discovered project, it scans source files and pushes code chunks to the Mnemonik API
31
+ 3. It watches for file changes and incrementally updates the index
32
+ 4. Every 5 minutes, it re-scans roots to discover new projects, handle folder renames, and drop deleted projects
33
+
34
+ ## Commands
35
+
36
+ | Command | Description |
37
+ |---------|-------------|
38
+ | `mnemonik-scanner start [options]` | Start the daemon |
39
+ | `mnemonik-scanner stop` | Stop the running daemon |
40
+ | `mnemonik-scanner status` | Show daemon status and watched projects |
41
+ | `mnemonik-scanner log` | Show recent log output |
42
+ | `mnemonik-scanner help` | Show usage information |
43
+
44
+ ### Start Options
45
+
46
+ | Option | Description |
47
+ |--------|-------------|
48
+ | `--key <api-key>` | Mnemonik API key (or set `MNEMONIK_API_KEY` env var) |
49
+ | `--server <url>` | Server URL (default: `https://api.mnemonik.dev`) |
50
+ | `--roots <dirs>` | Comma-separated directories to scan for projects |
51
+
52
+ ## Configuration
53
+
54
+ The daemon saves its configuration to `~/.mnemonik/scanner.json` with `0600` permissions (owner read/write only).
55
+
56
+ You can also set the API key via the `MNEMONIK_API_KEY` environment variable, which takes precedence over the config file and is never written to disk.
57
+
58
+ ### Files
59
+
60
+ | Path | Purpose |
61
+ |------|---------|
62
+ | `~/.mnemonik/scanner.json` | Persistent configuration |
63
+ | `~/.mnemonik/daemon.pid` | PID file for the running daemon |
64
+ | `~/.mnemonik/scanner.log` | Log file (rotated at 5MB) |
65
+
66
+ ## What Gets Indexed
67
+
68
+ The scanner indexes code chunks (functions, classes, modules) from these file types:
69
+
70
+ `.ts` `.tsx` `.js` `.jsx` `.py` `.rs` `.go` `.java` `.c` `.cpp` `.h` `.cs` `.rb` `.php` `.swift` `.kt` `.md`
71
+
72
+ It respects `.gitignore` and skips common directories (`node_modules`, `.git`, `dist`, `build`, etc.). Only code structure is indexed — binary files and non-code assets are ignored.
73
+
74
+ ## Resource Usage
75
+
76
+ The daemon is designed to run continuously with minimal impact:
77
+
78
+ - **Memory**: Capped at 256MB
79
+ - **CPU**: Event-driven (idle when no files change)
80
+ - **Disk**: Log rotation at 5MB
81
+ - **Network**: Only changed files are pushed (hash-based diffing)
82
+
83
+ ## Requirements
84
+
85
+ - Node.js 20 or later
86
+ - A Mnemonik account and API key ([sign up](https://mnemonik.dev))
87
+
88
+ ## License
89
+
90
+ Proprietary. See [mnemonik.dev/terms](https://mnemonik.dev/terms) for details.
package/dist/client.d.ts CHANGED
@@ -28,5 +28,6 @@ export declare class MnemonikClient {
28
28
  pushFiles(projectId: string, files: ScanPushFile[]): Promise<{
29
29
  success: boolean;
30
30
  }>;
31
+ sendHeartbeat(projectId: string): Promise<void>;
31
32
  healthCheck(): Promise<boolean>;
32
33
  }
package/dist/client.js CHANGED
@@ -57,6 +57,9 @@ export class MnemonikClient {
57
57
  }
58
58
  return { success: true };
59
59
  }
60
+ async sendHeartbeat(projectId) {
61
+ await this.request('/api/v1/scan/heartbeat', { projectId });
62
+ }
60
63
  async healthCheck() {
61
64
  try {
62
65
  const res = await fetch(`${this.serverUrl}/api/v1/health`, {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/daemon.d.ts CHANGED
@@ -1,25 +1,37 @@
1
1
  export interface DaemonConfig {
2
- projectId: string;
3
- projectRoot: string;
4
2
  serverUrl: string;
5
3
  apiKey: string;
4
+ roots: string[];
5
+ refreshIntervalMs?: number;
6
+ maxConcurrentScans?: number;
6
7
  }
7
8
  export declare class ScannerDaemon {
8
9
  private config;
9
10
  private client;
10
11
  private scanner;
11
- private watcher;
12
- private pendingRetries;
13
- private retryTimer;
12
+ private projects;
13
+ private refreshTimer;
14
+ private heartbeatTimer;
15
+ private discovery;
16
+ private refreshIntervalMs;
17
+ private maxConcurrentScans;
14
18
  constructor(config: DaemonConfig);
15
19
  start(): Promise<void>;
16
- private waitForServer;
17
- getProjectRoot(): string;
18
- getProjectId(): string;
19
20
  stop(): Promise<void>;
20
- private startRetryLoop;
21
+ private sendHeartbeats;
22
+ getWatchedProjects(): Array<{
23
+ projectId: string;
24
+ path: string;
25
+ name?: string;
26
+ }>;
27
+ /**
28
+ * Discover projects from configured roots and reconcile with current watch list.
29
+ */
30
+ refreshProjects(): Promise<void>;
31
+ private addProject;
32
+ private waitForServer;
21
33
  private initialScan;
22
- private startWatching;
23
34
  private handleChanges;
35
+ private startRetryLoop;
24
36
  private groupChunksByFile;
25
37
  }
package/dist/daemon.js CHANGED
@@ -4,25 +4,149 @@ import { join } from 'path';
4
4
  import { CodeScanner } from '@mnemonik/shared';
5
5
  import { MnemonikClient } from './client.js';
6
6
  import { FileWatcher } from './watcher.js';
7
+ import { ProjectDiscovery } from './discovery.js';
7
8
  export class ScannerDaemon {
8
9
  config;
9
10
  client;
10
11
  scanner;
11
- watcher = null;
12
- pendingRetries = new Set();
13
- retryTimer = null;
12
+ projects = new Map();
13
+ refreshTimer = null;
14
+ heartbeatTimer = null;
15
+ discovery;
16
+ refreshIntervalMs;
17
+ maxConcurrentScans;
14
18
  constructor(config) {
15
19
  this.config = config;
16
20
  this.client = new MnemonikClient(config.serverUrl, config.apiKey);
17
21
  this.scanner = new CodeScanner();
22
+ this.discovery = new ProjectDiscovery(config.roots);
23
+ this.refreshIntervalMs = config.refreshIntervalMs ?? 300_000; // 5 min
24
+ this.maxConcurrentScans = config.maxConcurrentScans ?? 5;
18
25
  }
19
26
  async start() {
20
- console.log(`[scanner] Starting daemon for project: ${this.config.projectId}`);
27
+ console.log(`[scanner] Starting daemon`);
21
28
  console.log(`[scanner] Server: ${this.config.serverUrl}`);
22
- console.log(`[scanner] Root: ${this.config.projectRoot}`);
29
+ console.log(`[scanner] Roots: ${this.config.roots.join(', ')}`);
23
30
  await this.waitForServer();
24
- await this.initialScan();
25
- await this.startWatching();
31
+ await this.refreshProjects();
32
+ this.refreshTimer = setInterval(() => {
33
+ this.refreshProjects().catch((err) => {
34
+ console.warn('[scanner] Refresh failed:', err.message);
35
+ });
36
+ }, this.refreshIntervalMs);
37
+ this.refreshTimer.unref();
38
+ // Send heartbeat immediately, then every 60s so session_bootstrap
39
+ // can reliably detect daemon liveness without waiting for a file scan.
40
+ await this.sendHeartbeats();
41
+ this.heartbeatTimer = setInterval(() => {
42
+ this.sendHeartbeats().catch((err) => {
43
+ console.warn('[scanner] Heartbeat failed:', err.message);
44
+ });
45
+ }, 60_000);
46
+ this.heartbeatTimer.unref();
47
+ console.log('[scanner] Watching for changes.');
48
+ }
49
+ async stop() {
50
+ if (this.refreshTimer) {
51
+ clearInterval(this.refreshTimer);
52
+ this.refreshTimer = null;
53
+ }
54
+ if (this.heartbeatTimer) {
55
+ clearInterval(this.heartbeatTimer);
56
+ this.heartbeatTimer = null;
57
+ }
58
+ for (const project of this.projects.values()) {
59
+ project.watcher.stop();
60
+ if (project.retryTimer)
61
+ clearInterval(project.retryTimer);
62
+ }
63
+ this.projects.clear();
64
+ console.log('[scanner] Daemon stopped');
65
+ }
66
+ async sendHeartbeats() {
67
+ for (const { projectId } of this.projects.values()) {
68
+ await this.client.sendHeartbeat(projectId).catch((err) => {
69
+ console.warn(`[scanner] Heartbeat failed for ${projectId}:`, err.message);
70
+ });
71
+ }
72
+ }
73
+ getWatchedProjects() {
74
+ return Array.from(this.projects.values()).map((p) => ({
75
+ projectId: p.projectId,
76
+ path: p.path,
77
+ name: p.name,
78
+ }));
79
+ }
80
+ /**
81
+ * Discover projects from configured roots and reconcile with current watch list.
82
+ */
83
+ async refreshProjects() {
84
+ const discovered = await this.discovery.discover();
85
+ const discoveredMap = new Map(discovered.map((d) => [d.projectId, d]));
86
+ // Remove projects no longer discovered
87
+ for (const [projectId, project] of this.projects) {
88
+ if (!discoveredMap.has(projectId)) {
89
+ console.log(`[scanner] Project removed: ${project.name ?? projectId} (${project.path})`);
90
+ project.watcher.stop();
91
+ if (project.retryTimer)
92
+ clearInterval(project.retryTimer);
93
+ this.projects.delete(projectId);
94
+ }
95
+ }
96
+ // Add new projects or handle path changes
97
+ for (const discovered_project of discoveredMap.values()) {
98
+ const existing = this.projects.get(discovered_project.projectId);
99
+ if (!existing) {
100
+ // New project
101
+ await this.addProject(discovered_project);
102
+ }
103
+ else if (existing.path !== discovered_project.path) {
104
+ // Path changed (folder renamed/moved)
105
+ console.log(`[scanner] Project moved: ${existing.name ?? existing.projectId} ` +
106
+ `${existing.path} → ${discovered_project.path}`);
107
+ existing.watcher.stop();
108
+ if (existing.retryTimer)
109
+ clearInterval(existing.retryTimer);
110
+ this.projects.delete(discovered_project.projectId);
111
+ await this.addProject(discovered_project);
112
+ }
113
+ }
114
+ console.log(`[scanner] Watching ${this.projects.size} project(s)`);
115
+ }
116
+ async addProject(discovered) {
117
+ const label = discovered.projectName ?? discovered.projectId.slice(0, 8);
118
+ console.log(`[scanner] Adding project: ${label} (${discovered.path})`);
119
+ try {
120
+ await this.initialScan(discovered.projectId, discovered.path);
121
+ }
122
+ catch (err) {
123
+ console.warn(`[scanner] Initial scan failed for ${label}:`, err.message);
124
+ }
125
+ const watcher = new FileWatcher(discovered.path, (changedFiles) => this.handleChanges(discovered.projectId, discovered.path, changedFiles), 500, (err) => {
126
+ console.warn(`[scanner] Root watcher error for ${label}: ${err.message}. Removing project.`);
127
+ const project = this.projects.get(discovered.projectId);
128
+ if (project) {
129
+ project.watcher.stop();
130
+ if (project.retryTimer)
131
+ clearInterval(project.retryTimer);
132
+ this.projects.delete(discovered.projectId);
133
+ }
134
+ });
135
+ try {
136
+ await watcher.start();
137
+ }
138
+ catch (err) {
139
+ console.warn(`[scanner] Failed to start watcher for ${label}:`, err.message);
140
+ return;
141
+ }
142
+ this.projects.set(discovered.projectId, {
143
+ projectId: discovered.projectId,
144
+ path: discovered.path,
145
+ name: discovered.projectName,
146
+ watcher,
147
+ pendingRetries: new Set(),
148
+ retryTimer: null,
149
+ });
26
150
  }
27
151
  async waitForServer() {
28
152
  let logged = false;
@@ -47,108 +171,83 @@ export class ScannerDaemon {
47
171
  }
48
172
  throw new Error(`Server unreachable after ${maxRetries} attempts`);
49
173
  }
50
- getProjectRoot() {
51
- return this.config.projectRoot;
52
- }
53
- getProjectId() {
54
- return this.config.projectId;
55
- }
56
- async stop() {
57
- this.watcher?.stop();
58
- if (this.retryTimer)
59
- clearInterval(this.retryTimer);
60
- console.log('[scanner] Daemon stopped');
61
- }
62
- startRetryLoop() {
63
- if (this.retryTimer)
64
- return;
65
- console.log(`[scanner] ${this.pendingRetries.size} file(s) queued for retry`);
66
- this.retryTimer = setInterval(async () => {
67
- if (this.pendingRetries.size === 0) {
68
- if (this.retryTimer)
69
- clearInterval(this.retryTimer);
70
- this.retryTimer = null;
71
- return;
72
- }
73
- const files = [...this.pendingRetries];
74
- this.pendingRetries.clear();
75
- await this.handleChanges(files);
76
- }, 10_000);
77
- this.retryTimer.unref();
78
- }
79
- async initialScan() {
80
- console.log('[scanner] Starting initial scan...');
174
+ async initialScan(projectId, projectRoot) {
81
175
  const startTime = Date.now();
82
- const chunks = await this.scanner.scanDirectory(this.config.projectRoot);
83
- console.log(`[scanner] Scanned ${chunks.length} chunks locally`);
84
- const serverHashes = await this.client.getStatus(this.config.projectId);
85
- console.log(`[scanner] Server knows ${serverHashes.size} files`);
86
- const files = await this.groupChunksByFile(chunks);
176
+ const chunks = await this.scanner.scanDirectory(projectRoot);
177
+ const serverHashes = await this.client.getStatus(projectId);
178
+ const files = await this.groupChunksByFile(chunks, projectRoot);
87
179
  const filesToPush = files.filter((f) => {
88
180
  const serverHash = serverHashes.get(f.path);
89
181
  return !serverHash || serverHash !== f.hash;
90
182
  });
91
- if (filesToPush.length === 0) {
92
- console.log('[scanner] All files up to date, nothing to push');
93
- }
94
- else {
95
- console.log(`[scanner] Pushing ${filesToPush.length} changed files...`);
96
- await this.client.pushFiles(this.config.projectId, filesToPush);
97
- console.log(`[scanner] Push complete`);
183
+ if (filesToPush.length > 0) {
184
+ console.log(`[scanner] Pushing ${filesToPush.length} changed files for ${projectId.slice(0, 8)}...`);
185
+ await this.client.pushFiles(projectId, filesToPush);
98
186
  }
99
187
  const duration = ((Date.now() - startTime) / 1000).toFixed(1);
100
- console.log(`[scanner] Initial scan complete in ${duration}s`);
101
- }
102
- async startWatching() {
103
- this.watcher = new FileWatcher(this.config.projectRoot, (changedFiles) => this.handleChanges(changedFiles), 500);
104
- await this.watcher.start();
188
+ console.log(`[scanner] Scan complete for ${projectId.slice(0, 8)}: ` +
189
+ `${chunks.length} chunks, ${filesToPush.length} pushed (${duration}s)`);
105
190
  }
106
- async handleChanges(changedFiles) {
191
+ async handleChanges(projectId, projectRoot, changedFiles) {
192
+ const project = this.projects.get(projectId);
193
+ if (!project)
194
+ return;
107
195
  try {
108
- const absPaths = changedFiles.map((rel) => join(this.config.projectRoot, rel));
109
- const chunks = await this.scanner.scanFiles(absPaths, this.config.projectRoot);
196
+ const absPaths = changedFiles.map((rel) => join(projectRoot, rel));
197
+ const chunks = await this.scanner.scanFiles(absPaths, projectRoot);
110
198
  if (chunks.length === 0)
111
199
  return;
112
- const files = await this.groupChunksByFile(chunks);
113
- // Push in batches, only retrying files from failed batches
200
+ const files = await this.groupChunksByFile(chunks, projectRoot);
114
201
  const batchSize = 25;
115
202
  const succeededPaths = new Set();
116
203
  let hadFailure = false;
117
204
  for (let i = 0; i < files.length; i += batchSize) {
118
205
  const batch = files.slice(i, i + batchSize);
119
206
  try {
120
- await this.client.pushFiles(this.config.projectId, batch);
207
+ await this.client.pushFiles(projectId, batch);
121
208
  for (const f of batch)
122
209
  succeededPaths.add(f.path);
123
210
  }
124
211
  catch {
125
212
  hadFailure = true;
126
213
  for (const f of batch)
127
- this.pendingRetries.add(f.path);
214
+ project.pendingRetries.add(f.path);
128
215
  }
129
216
  }
130
217
  if (succeededPaths.size > 0) {
131
- console.log(`[scanner] Pushed ${succeededPaths.size} changed file(s): ${[...succeededPaths].join(', ')}`);
218
+ console.log(`[scanner] [${projectId.slice(0, 8)}] Pushed ${succeededPaths.size} file(s): ${[...succeededPaths].join(', ')}`);
132
219
  }
133
220
  if (hadFailure) {
134
- console.warn(`[scanner] ${this.pendingRetries.size} file(s) failed, queued for retry`);
135
- this.startRetryLoop();
221
+ console.warn(`[scanner] [${projectId.slice(0, 8)}] ${project.pendingRetries.size} file(s) failed, queued for retry`);
222
+ this.startRetryLoop(project);
136
223
  }
137
224
  }
138
225
  catch (err) {
139
- console.error('[scanner] Error handling changes:', err);
226
+ console.error(`[scanner] [${projectId.slice(0, 8)}] Error handling changes:`, err);
140
227
  }
141
228
  }
142
- async groupChunksByFile(chunks) {
229
+ startRetryLoop(project) {
230
+ if (project.retryTimer)
231
+ return;
232
+ project.retryTimer = setInterval(async () => {
233
+ if (project.pendingRetries.size === 0) {
234
+ if (project.retryTimer)
235
+ clearInterval(project.retryTimer);
236
+ project.retryTimer = null;
237
+ return;
238
+ }
239
+ const files = [...project.pendingRetries];
240
+ project.pendingRetries.clear();
241
+ await this.handleChanges(project.projectId, project.path, files);
242
+ }, 10_000);
243
+ project.retryTimer.unref();
244
+ }
245
+ async groupChunksByFile(chunks, projectRoot) {
143
246
  const fileMap = new Map();
144
247
  for (const chunk of chunks) {
145
248
  const key = chunk.filePath;
146
249
  if (!fileMap.has(key)) {
147
- fileMap.set(key, {
148
- path: key,
149
- hash: '',
150
- chunks: [],
151
- });
250
+ fileMap.set(key, { path: key, hash: '', chunks: [] });
152
251
  }
153
252
  const file = fileMap.get(key);
154
253
  file.chunks.push({
@@ -163,7 +262,7 @@ export class ScannerDaemon {
163
262
  }
164
263
  for (const file of fileMap.values()) {
165
264
  try {
166
- const absPath = join(this.config.projectRoot, file.path);
265
+ const absPath = join(projectRoot, file.path);
167
266
  const raw = await readFile(absPath, 'utf-8');
168
267
  file.hash = createHash('sha256').update(raw).digest('hex');
169
268
  }
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface DiscoveredProject {
2
+ projectId: string;
3
+ path: string;
4
+ projectName?: string;
5
+ }
6
+ export declare class ProjectDiscovery {
7
+ private roots;
8
+ private maxDepth;
9
+ private timeoutMs;
10
+ constructor(roots: string[], options?: {
11
+ maxDepth?: number;
12
+ timeoutMs?: number;
13
+ });
14
+ /**
15
+ * Discover all projects with .mnemonik.json files under the configured roots.
16
+ * Deduplicates by projectId (same project found at multiple paths = first wins).
17
+ */
18
+ discover(): Promise<DiscoveredProject[]>;
19
+ private walkWithTimeout;
20
+ private walk;
21
+ }
@@ -0,0 +1,107 @@
1
+ import { readFile, readdir } from 'fs/promises';
2
+ import { join, resolve } from 'path';
3
+ /** Directories to skip during discovery walk */
4
+ const SKIP_DIRS = new Set([
5
+ 'node_modules',
6
+ '.git',
7
+ 'dist',
8
+ 'build',
9
+ '.next',
10
+ '.nuxt',
11
+ '.output',
12
+ '__pycache__',
13
+ '.venv',
14
+ 'venv',
15
+ '.tox',
16
+ 'target',
17
+ '.cache',
18
+ 'coverage',
19
+ '.turbo',
20
+ '.vercel',
21
+ '.svelte-kit',
22
+ ]);
23
+ export class ProjectDiscovery {
24
+ roots;
25
+ maxDepth;
26
+ timeoutMs;
27
+ constructor(roots, options) {
28
+ this.roots = roots;
29
+ this.maxDepth = options?.maxDepth ?? 3;
30
+ this.timeoutMs = options?.timeoutMs ?? 30_000;
31
+ }
32
+ /**
33
+ * Discover all projects with .mnemonik.json files under the configured roots.
34
+ * Deduplicates by projectId (same project found at multiple paths = first wins).
35
+ */
36
+ async discover() {
37
+ const seen = new Map();
38
+ for (const root of this.roots) {
39
+ const absRoot = resolve(root.replace(/^~/, process.env.HOME || ''));
40
+ try {
41
+ await this.walkWithTimeout(absRoot, 0, seen);
42
+ }
43
+ catch (err) {
44
+ if (err instanceof DiscoveryTimeoutError) {
45
+ console.warn(`[scanner] Discovery timeout for root: ${absRoot} (>${this.timeoutMs}ms)`);
46
+ }
47
+ else {
48
+ console.warn(`[scanner] Error scanning root ${absRoot}:`, err.message);
49
+ }
50
+ }
51
+ }
52
+ return Array.from(seen.values());
53
+ }
54
+ async walkWithTimeout(dir, depth, seen) {
55
+ const deadline = Date.now() + this.timeoutMs;
56
+ await this.walk(dir, depth, seen, deadline);
57
+ }
58
+ async walk(dir, depth, seen, deadline) {
59
+ if (depth > this.maxDepth)
60
+ return;
61
+ if (Date.now() > deadline)
62
+ throw new DiscoveryTimeoutError();
63
+ // Check for .mnemonik.json in this directory
64
+ const configPath = join(dir, '.mnemonik.json');
65
+ try {
66
+ const raw = await readFile(configPath, 'utf-8');
67
+ const parsed = JSON.parse(raw);
68
+ if (typeof parsed.projectId === 'string' && parsed.projectId.length > 0) {
69
+ if (!seen.has(parsed.projectId)) {
70
+ seen.set(parsed.projectId, {
71
+ projectId: parsed.projectId,
72
+ path: dir,
73
+ projectName: typeof parsed.projectName === 'string' ? parsed.projectName : undefined,
74
+ });
75
+ }
76
+ }
77
+ // Don't recurse into subdirectories of a project — the project owns this tree
78
+ return;
79
+ }
80
+ catch {
81
+ // No .mnemonik.json here, continue walking
82
+ }
83
+ // Recurse into subdirectories
84
+ try {
85
+ const entries = await readdir(dir, { withFileTypes: true });
86
+ for (const entry of entries) {
87
+ if (!entry.isDirectory())
88
+ continue;
89
+ if (SKIP_DIRS.has(entry.name))
90
+ continue;
91
+ if (entry.name.startsWith('.') && entry.name !== '.mnemonik')
92
+ continue;
93
+ await this.walk(join(dir, entry.name), depth + 1, seen, deadline);
94
+ }
95
+ }
96
+ catch {
97
+ // Permission denied or inaccessible directory
98
+ }
99
+ }
100
+ }
101
+ class DiscoveryTimeoutError extends Error {
102
+ constructor() {
103
+ super('Discovery walk timed out');
104
+ this.name = 'DiscoveryTimeoutError';
105
+ }
106
+ }
107
+ //# sourceMappingURL=discovery.js.map