wicked-brain 0.3.1 → 0.3.2
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/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { watch, readFileSync, existsSync, readdirSync } from "node:fs";
|
|
1
|
+
import { watch, readFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
|
|
@@ -106,15 +106,29 @@ export class FileWatcher {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
#scanAndHashProject(project) {
|
|
109
|
+
let indexed = 0;
|
|
109
110
|
this.#walkDir(project.path, (absPath) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
if (!this.#isCodeFile(absPath)) return;
|
|
112
|
+
try {
|
|
113
|
+
const stat = statSync(absPath);
|
|
114
|
+
if (stat.size > FileWatcher.#MAX_FILE_SIZE) return;
|
|
115
|
+
} catch { return; }
|
|
113
116
|
const relPath = normalizePath(`projects/${project.name}/${relative(project.path, absPath)}`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
try {
|
|
118
|
+
const content = readFileSync(absPath, "utf-8");
|
|
119
|
+
const hash = this.#hash(content);
|
|
120
|
+
this.#hashes.set(relPath, hash);
|
|
121
|
+
// Index project files on first scan (brain dirs are pre-indexed, project dirs are not)
|
|
122
|
+
this.#db.index({
|
|
123
|
+
id: relPath,
|
|
124
|
+
path: relPath,
|
|
125
|
+
content,
|
|
126
|
+
brain_id: this.#brainId,
|
|
127
|
+
});
|
|
128
|
+
indexed++;
|
|
129
|
+
} catch { /* binary or unreadable — skip */ }
|
|
117
130
|
});
|
|
131
|
+
console.log(`[watcher] Scanned project ${project.name}: ${indexed} files indexed`);
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
#walkDir(dir, callback) {
|
|
@@ -183,6 +197,12 @@ export class FileWatcher {
|
|
|
183
197
|
return;
|
|
184
198
|
}
|
|
185
199
|
|
|
200
|
+
if (!this.#isCodeFile(absPath)) return;
|
|
201
|
+
try {
|
|
202
|
+
const stat = statSync(absPath);
|
|
203
|
+
if (stat.size > FileWatcher.#MAX_FILE_SIZE) return;
|
|
204
|
+
} catch { return; }
|
|
205
|
+
|
|
186
206
|
try {
|
|
187
207
|
const content = readFileSync(absPath, "utf-8");
|
|
188
208
|
const newHash = this.#hash(content);
|
|
@@ -203,11 +223,40 @@ export class FileWatcher {
|
|
|
203
223
|
} catch {}
|
|
204
224
|
}
|
|
205
225
|
|
|
226
|
+
/** Max file size to index (1MB). Skips binaries and large generated files. */
|
|
227
|
+
static #MAX_FILE_SIZE = 1048576;
|
|
228
|
+
|
|
229
|
+
/** Text file extensions safe to read and index. */
|
|
230
|
+
static #CODE_EXTENSIONS = new Set([
|
|
231
|
+
// Web
|
|
232
|
+
".ts", ".tsx", ".js", ".jsx", ".mjs", ".mts", ".cjs",
|
|
233
|
+
".html", ".htm", ".css", ".scss", ".less", ".sass",
|
|
234
|
+
".vue", ".svelte", ".astro",
|
|
235
|
+
// Backend
|
|
236
|
+
".py", ".go", ".rs", ".java", ".cs", ".rb", ".php",
|
|
237
|
+
".kt", ".kts", ".scala", ".sc", ".ex", ".exs", ".erl",
|
|
238
|
+
// Systems
|
|
239
|
+
".c", ".cpp", ".cc", ".cxx", ".h", ".hpp", ".zig", ".nim", ".d",
|
|
240
|
+
".hs", ".lhs", ".ml", ".mli",
|
|
241
|
+
// Scripting
|
|
242
|
+
".lua", ".pl", ".pm", ".r", ".R", ".jl", ".sh", ".bash", ".zsh",
|
|
243
|
+
// Data / Config
|
|
244
|
+
".sql", ".graphql", ".gql", ".tf", ".yaml", ".yml",
|
|
245
|
+
".toml", ".json", ".jsonc", ".xml", ".csv",
|
|
246
|
+
// Mobile
|
|
247
|
+
".swift", ".dart",
|
|
248
|
+
// Other
|
|
249
|
+
".clj", ".cljs", ".cljc", ".edn", ".fs", ".fsx", ".fsi",
|
|
250
|
+
".gleam", ".sol", ".prisma", ".proto",
|
|
251
|
+
// Docs
|
|
252
|
+
".md", ".markdown", ".tex", ".txt", ".rst",
|
|
253
|
+
]);
|
|
254
|
+
|
|
206
255
|
#isCodeFile(absPath) {
|
|
207
256
|
const dot = absPath.lastIndexOf(".");
|
|
208
257
|
if (dot === -1) return false;
|
|
209
|
-
const ext = absPath.slice(dot);
|
|
210
|
-
return ext
|
|
258
|
+
const ext = absPath.slice(dot).toLowerCase();
|
|
259
|
+
return FileWatcher.#CODE_EXTENSIONS.has(ext);
|
|
211
260
|
}
|
|
212
261
|
|
|
213
262
|
#startPolling() {
|
package/server/package.json
CHANGED
|
@@ -71,8 +71,8 @@ Digital brain: {brain_id} | {total} indexed items | {chunks} chunks, {wiki} wiki
|
|
|
71
71
|
|
|
72
72
|
### How to use
|
|
73
73
|
|
|
74
|
-
- **Before responding**: call `wicked-brain:
|
|
75
|
-
- **Capture learnings**: call `wicked-brain:session-teardown
|
|
74
|
+
- **Before responding**: call `wicked-brain:agent` (context) to surface relevant knowledge
|
|
75
|
+
- **Capture learnings**: call `wicked-brain:agent` (session-teardown) at session end
|
|
76
76
|
- **Store a decision/pattern/gotcha**: call `wicked-brain:memory` (store mode)
|
|
77
77
|
- **Ask the brain**: call `wicked-brain:query` for cited answers
|
|
78
78
|
- **Available agents**: consolidate, context, session-teardown, onboard (via `wicked-brain:agent`)
|