diff options
| author | Agando <roduccomm@gmail.com> | 2026-06-04 06:01:04 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-06-04 06:01:04 +0200 |
| commit | a5023e61be61f2f2287342039addab6bb28ad2fd (patch) | |
| tree | 9b1b3c166869cd6fee91bffe1f4134513005b8b1 /modules/core/virtual-fs.js | |
| parent | 301f75ab03302a05b3c35950a3b0ab49f9f69ed6 (diff) | |
auto: 2026-06-04_06:00 changes
Diffstat (limited to 'modules/core/virtual-fs.js')
| -rw-r--r-- | modules/core/virtual-fs.js | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/modules/core/virtual-fs.js b/modules/core/virtual-fs.js index d2d3103..3ab25b1 100644 --- a/modules/core/virtual-fs.js +++ b/modules/core/virtual-fs.js @@ -3,6 +3,7 @@ class VirtualFileSystem { this.root = { type: 'dir', content: {} }; this.currentPath = []; this._ready = this.loadFromStorage(); + this._conceptCache = null; } _u8ToBase64(u8) { let s = ''; @@ -82,6 +83,27 @@ class VirtualFileSystem { } catch (e) { console.error('FS save error:', e); } }, 2000); } + getCurrentPath() { + return '/' + this.currentPath.join('/'); + } + setCurrentPath(path) { + const segs = this._toAbsoluteSegments(path); + if (segs === null) return false; + this.currentPath = segs; + return true; + } + _loadConceptIndex() { + if (this._conceptCache) return this._conceptCache; + try { + const raw = this.readFile('/.semantic_index/map.json'); + if (raw) { + this._conceptCache = JSON.parse(raw); + return this._conceptCache; + } + } catch (e) {} + return null; + } + _clearConceptCache() { this._conceptCache = null; } getCurrentDir() { let dir = this.root; for (let part of this.currentPath) { @@ -130,6 +152,18 @@ class VirtualFileSystem { return dir; } ls(path) { + // concept:// listing + if (path && path.startsWith('concept://')) { + const concept = path.replace('concept://', '').replace(/\/.*$/, '').toLowerCase(); + const index = this._loadConceptIndex(); + if (!index) return []; + let matches = index[concept] || []; + if (matches.length === 0) { + const fuzzy = Object.keys(index).filter(k => k.includes(concept) || concept.includes(k)); + if (fuzzy.length > 0) matches = index[fuzzy[0]]; + } + return (matches || []).map(m => ({ name: m.path.split('/').pop(), type: 'file', path: m.path, size: 0, concept: true })); + } let dir; if (path) { const resolved = this._resolvePath(path); @@ -161,6 +195,24 @@ class VirtualFileSystem { return true; } readFile(path) { + // concept:// URI resolution + if (path && path.startsWith('concept://')) { + const concept = path.replace('concept://', '').replace(/\/.*$/, '').toLowerCase(); + try { + const index = this._loadConceptIndex(); + if (!index) return 'No semantic index found. Run nvfs-index first.'; + let matches = index[concept]; + if (!matches) { + const fuzzy = Object.keys(index).filter(k => k.includes(concept) || concept.includes(k)); + if (fuzzy.length > 0) matches = index[fuzzy[0]]; + } + if (!matches || matches.length === 0) return `No files found for concept "${concept}"`; + const first = matches[0]; + const content = this.readFile(first.path); + if (content) return `--- ${first.path} (concept://${concept}) ---\n${content}`; + return `Concept "${concept}" → ${matches.length} file(s):\n${matches.map(m => ` ${m.path} — ${m.summary || ''}`).join('\n')}`; + } catch (e) { return `concept:// error: ${e.message}`; } + } const resolved = this._resolvePath(path); if (!resolved || !resolved.name) return null; const node = resolved.dir.content[resolved.name]; |