* Walk the knowledge directory and build an in-memory index of available * notes. Each entry: { path, name, keywords[], heading, contentFn }. * contentFn is a thunk so we don't read every file at startup.
()
| 77 | * contentFn is a thunk so we don't read every file at startup. |
| 78 | */ |
| 79 | _buildIndex() { |
| 80 | if (this._index) return this._index; |
| 81 | const dir = this._resolveDir(); |
| 82 | if (!dir) return (this._index = []); |
| 83 | |
| 84 | const entries = []; |
| 85 | const walk = (sub) => { |
| 86 | let listing; |
| 87 | try { listing = fs.readdirSync(sub, { withFileTypes: true }); } |
| 88 | catch { return; } |
| 89 | for (const ent of listing) { |
| 90 | const full = path.join(sub, ent.name); |
| 91 | if (ent.isDirectory()) walk(full); |
| 92 | else if (ent.isFile() && /\.(md|txt)$/i.test(ent.name)) { |
| 93 | entries.push(this._parseEntry(full, dir)); |
| 94 | } |
| 95 | } |
| 96 | }; |
| 97 | walk(dir); |
| 98 | this._index = entries.filter(Boolean); |
| 99 | return this._index; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Parse a single knowledge file's metadata without loading its full content. |
no test coverage detected