MCPcopy
hub / github.com/coder/mux / LocalMemoryStore

Class LocalMemoryStore

src/node/services/memoryService.ts:296–418  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

294}
295
296class LocalMemoryStore implements MemoryStore {
297 constructor(readonly physicalRoot: string) {}
298
299 private abs(relPath: string): string {
300 return relPath === "" ? this.physicalRoot : path.join(this.physicalRoot, ...relPath.split("/"));
301 }
302
303 assertRootSafe(): Promise<void> {
304 // Host-local roots are trusted; per-target symlink escape checks happen in assertContained().
305 return Promise.resolve();
306 }
307
308 async ensureRoot(): Promise<void> {
309 await this.assertRootSafe();
310 await fsPromises.mkdir(this.physicalRoot, { recursive: true });
311 }
312
313 async listFiles(): Promise<string[]> {
314 const results: string[] = [];
315 const walk = async (dirRel: string): Promise<void> => {
316 // Bounded walk: files may have been edited outside MemoryService. +1 lets
317 // callers detect overflow (e.g. the index logs its truncation).
318 if (results.length > MEMORY_MAX_FILES_PER_SCOPE) return;
319 let entries;
320 try {
321 entries = await fsPromises.readdir(this.abs(dirRel), { withFileTypes: true });
322 } catch {
323 return; // Self-healing: missing/unreadable dirs list as empty.
324 }
325 // Iterate in path-string order — directories key as "name/" so the DFS
326 // emits exact global lexicographic order ("a.md" < "a/...", `.` < `/`).
327 // The capped subset is deterministic across platforms.
328 const sortKey = (entry: (typeof entries)[number]) =>
329 entry.isDirectory() ? `${entry.name}/` : entry.name;
330 entries.sort((a, b) => {
331 const ka = sortKey(a);
332 const kb = sortKey(b);
333 return ka < kb ? -1 : ka > kb ? 1 : 0;
334 });
335 for (const entry of entries) {
336 // Per-entry cap: a single flat directory can exceed the cap on its own.
337 if (results.length > MEMORY_MAX_FILES_PER_SCOPE) return;
338 if (entry.name.startsWith(".")) continue;
339 const childRel = dirRel === "" ? entry.name : `${dirRel}/${entry.name}`;
340 if (entry.isDirectory()) {
341 await walk(childRel);
342 } else if (entry.isFile()) {
343 results.push(childRel);
344 }
345 }
346 };
347 await walk("");
348 return results.sort();
349 }
350
351 async kind(relPath: string): Promise<MemoryEntryKind> {
352 try {
353 const stat = await fsPromises.stat(this.abs(relPath));

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected