@runcore-sh/runcore 0.4.0 → 0.5.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/dictionary.json +2 -2
- package/dist/activity/log.js +2 -2
- package/dist/activity/log.js.map +1 -1
- package/dist/agents/governed-spawn.d.ts.map +1 -1
- package/dist/cli.js +101 -11
- package/dist/cli.js.map +1 -1
- package/dist/extensions/cache.d.ts +57 -0
- package/dist/extensions/cache.d.ts.map +1 -0
- package/dist/extensions/cache.js +173 -0
- package/dist/extensions/cache.js.map +1 -0
- package/dist/extensions/client.d.ts +55 -0
- package/dist/extensions/client.d.ts.map +1 -0
- package/dist/extensions/client.js +120 -0
- package/dist/extensions/client.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +50 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +166 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/manifest.d.ts +38 -0
- package/dist/extensions/manifest.d.ts.map +1 -0
- package/dist/extensions/manifest.js +17 -0
- package/dist/extensions/manifest.js.map +1 -0
- package/dist/extensions/stubs.d.ts +27 -0
- package/dist/extensions/stubs.d.ts.map +1 -0
- package/dist/extensions/stubs.js +45 -0
- package/dist/extensions/stubs.js.map +1 -0
- package/dist/lib/audit.js +2 -2
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/brain-migrate.d.ts +21 -0
- package/dist/lib/brain-migrate.d.ts.map +1 -0
- package/dist/lib/brain-migrate.js +137 -0
- package/dist/lib/brain-migrate.js.map +1 -0
- package/dist/lib/paths.d.ts +27 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +65 -0
- package/dist/lib/paths.js.map +1 -1
- package/dist/llm/call-log.d.ts +40 -0
- package/dist/llm/call-log.d.ts.map +1 -0
- package/dist/llm/call-log.js +35 -0
- package/dist/llm/call-log.js.map +1 -0
- package/dist/llm/complete.d.ts +6 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +27 -0
- package/dist/llm/complete.js.map +1 -1
- package/dist/mcp-server.js +118 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/memory/file-backed.d.ts +4 -0
- package/dist/memory/file-backed.d.ts.map +1 -1
- package/dist/memory/file-backed.js +4 -0
- package/dist/memory/file-backed.js.map +1 -1
- package/dist/memory/vector-index.d.ts +4 -12
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +11 -93
- package/dist/memory/vector-index.js.map +1 -1
- package/dist/search/brain-docs.d.ts +17 -7
- package/dist/search/brain-docs.d.ts.map +1 -1
- package/dist/search/brain-docs.js +170 -52
- package/dist/search/brain-docs.js.map +1 -1
- package/dist/search/brain-rag.d.ts +45 -0
- package/dist/search/brain-rag.d.ts.map +1 -0
- package/dist/search/brain-rag.js +275 -0
- package/dist/search/brain-rag.js.map +1 -0
- package/dist/search/chunker.d.ts +24 -0
- package/dist/search/chunker.d.ts.map +1 -0
- package/dist/search/chunker.js +95 -0
- package/dist/search/chunker.js.map +1 -0
- package/dist/search/embedder.d.ts +16 -0
- package/dist/search/embedder.d.ts.map +1 -0
- package/dist/search/embedder.js +108 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/file-watcher.d.ts +11 -0
- package/dist/search/file-watcher.d.ts.map +1 -0
- package/dist/search/file-watcher.js +86 -0
- package/dist/search/file-watcher.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +814 -472
- package/dist/server.js.map +1 -1
- package/dist/sessions/store.d.ts +9 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +78 -2
- package/dist/settings.js.map +1 -1
- package/dist/tracing/init.d.ts +1 -1
- package/dist/tracing/init.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/module-tiers.json +164 -0
- package/package.json +9 -13
- package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
- package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
- package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
- package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
- package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
- package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
- package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
- package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
- package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
- package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
- package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
- package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
- package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
- package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
- package/public/index.html +379 -59
- package/dist/agents/autonomous.js +0 -749
- package/dist/agents/autonomous.js.map +0 -1
- package/dist/agents/commit.js +0 -113
- package/dist/agents/commit.js.map +0 -1
- package/dist/agents/continue.js +0 -158
- package/dist/agents/continue.js.map +0 -1
- package/dist/agents/cooldown.js +0 -397
- package/dist/agents/cooldown.js.map +0 -1
- package/dist/agents/dedup-guard.js +0 -131
- package/dist/agents/dedup-guard.js.map +0 -1
- package/dist/agents/feed.js +0 -176
- package/dist/agents/feed.js.map +0 -1
- package/dist/agents/governance.js +0 -292
- package/dist/agents/governance.js.map +0 -1
- package/dist/agents/governed-spawn.js +0 -192
- package/dist/agents/governed-spawn.js.map +0 -1
- package/dist/agents/heartbeat.js +0 -324
- package/dist/agents/heartbeat.js.map +0 -1
- package/dist/agents/instance-manager.js +0 -850
- package/dist/agents/instance-manager.js.map +0 -1
- package/dist/agents/issue-reporter.js +0 -123
- package/dist/agents/issue-reporter.js.map +0 -1
- package/dist/agents/issues.js +0 -141
- package/dist/agents/issues.js.map +0 -1
- package/dist/agents/locks.js +0 -234
- package/dist/agents/locks.js.map +0 -1
- package/dist/agents/memory.js +0 -93
- package/dist/agents/memory.js.map +0 -1
- package/dist/agents/monitor.js +0 -235
- package/dist/agents/monitor.js.map +0 -1
- package/dist/agents/orchestration.js +0 -715
- package/dist/agents/orchestration.js.map +0 -1
- package/dist/agents/recover.js +0 -166
- package/dist/agents/recover.js.map +0 -1
- package/dist/agents/reflection.js +0 -199
- package/dist/agents/reflection.js.map +0 -1
- package/dist/agents/runtime/bus.js +0 -174
- package/dist/agents/runtime/bus.js.map +0 -1
- package/dist/agents/runtime/config.js +0 -101
- package/dist/agents/runtime/config.js.map +0 -1
- package/dist/agents/runtime/driver.js +0 -214
- package/dist/agents/runtime/driver.js.map +0 -1
- package/dist/agents/runtime/errors.js +0 -40
- package/dist/agents/runtime/errors.js.map +0 -1
- package/dist/agents/runtime/index.js +0 -54
- package/dist/agents/runtime/index.js.map +0 -1
- package/dist/agents/runtime/lifecycle.js +0 -116
- package/dist/agents/runtime/lifecycle.js.map +0 -1
- package/dist/agents/runtime/manager.js +0 -948
- package/dist/agents/runtime/manager.js.map +0 -1
- package/dist/agents/runtime/registry.js +0 -195
- package/dist/agents/runtime/registry.js.map +0 -1
- package/dist/agents/runtime/resources.js +0 -146
- package/dist/agents/runtime/resources.js.map +0 -1
- package/dist/agents/runtime/types.js +0 -24
- package/dist/agents/runtime/types.js.map +0 -1
- package/dist/agents/spawn-policy.js +0 -202
- package/dist/agents/spawn-policy.js.map +0 -1
- package/dist/agents/spawn.js +0 -970
- package/dist/agents/spawn.js.map +0 -1
- package/dist/agents/triage.js +0 -81
- package/dist/agents/triage.js.map +0 -1
- package/dist/agents/workflow.js +0 -543
- package/dist/agents/workflow.js.map +0 -1
- package/dist/avatar/client.js +0 -172
- package/dist/avatar/client.js.map +0 -1
- package/dist/avatar/sidecar.js +0 -125
- package/dist/avatar/sidecar.js.map +0 -1
- package/dist/browser/sessions.js +0 -122
- package/dist/browser/sessions.js.map +0 -1
- package/dist/capabilities/definitions/browser.js +0 -242
- package/dist/capabilities/definitions/browser.js.map +0 -1
- package/dist/channels/whatsapp.js +0 -200
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/credentials/store.js +0 -189
- package/dist/credentials/store.js.map +0 -1
- package/dist/files/deep-index.js +0 -337
- package/dist/files/deep-index.js.map +0 -1
- package/dist/files/extract.js +0 -33
- package/dist/files/extract.js.map +0 -1
- package/dist/files/gdrive.js +0 -246
- package/dist/files/gdrive.js.map +0 -1
- package/dist/github/client.js +0 -408
- package/dist/github/client.js.map +0 -1
- package/dist/github/commit-analysis.js +0 -276
- package/dist/github/commit-analysis.js.map +0 -1
- package/dist/github/contributor-stats.js +0 -119
- package/dist/github/contributor-stats.js.map +0 -1
- package/dist/github/issue-sla.js +0 -220
- package/dist/github/issue-sla.js.map +0 -1
- package/dist/github/issue-triage.js +0 -286
- package/dist/github/issue-triage.js.map +0 -1
- package/dist/github/pr-readiness.js +0 -197
- package/dist/github/pr-readiness.js.map +0 -1
- package/dist/github/pr-review.js +0 -410
- package/dist/github/pr-review.js.map +0 -1
- package/dist/github/release-notes.js +0 -227
- package/dist/github/release-notes.js.map +0 -1
- package/dist/github/repo-health.js +0 -303
- package/dist/github/repo-health.js.map +0 -1
- package/dist/github/retry.js +0 -117
- package/dist/github/retry.js.map +0 -1
- package/dist/github/types.js +0 -8
- package/dist/github/types.js.map +0 -1
- package/dist/github/webhooks.js +0 -153
- package/dist/github/webhooks.js.map +0 -1
- package/dist/google/auth.js +0 -325
- package/dist/google/auth.js.map +0 -1
- package/dist/google/calendar-timer.js +0 -91
- package/dist/google/calendar-timer.js.map +0 -1
- package/dist/google/calendar.js +0 -270
- package/dist/google/calendar.js.map +0 -1
- package/dist/google/docs.js +0 -309
- package/dist/google/docs.js.map +0 -1
- package/dist/google/gmail-send.js +0 -219
- package/dist/google/gmail-send.js.map +0 -1
- package/dist/google/gmail-timer.js +0 -223
- package/dist/google/gmail-timer.js.map +0 -1
- package/dist/google/gmail.js +0 -470
- package/dist/google/gmail.js.map +0 -1
- package/dist/google/plugin.js +0 -169
- package/dist/google/plugin.js.map +0 -1
- package/dist/google/tasks-timer.js +0 -107
- package/dist/google/tasks-timer.js.map +0 -1
- package/dist/google/tasks.js +0 -331
- package/dist/google/tasks.js.map +0 -1
- package/dist/google/temporal.js +0 -176
- package/dist/google/temporal.js.map +0 -1
- package/dist/integrations/gate.js +0 -100
- package/dist/integrations/gate.js.map +0 -1
- package/dist/integrations/github.js +0 -331
- package/dist/integrations/github.js.map +0 -1
- package/dist/integrations/google-tasks.js +0 -432
- package/dist/integrations/google-tasks.js.map +0 -1
- package/dist/mdns.js +0 -110
- package/dist/mdns.js.map +0 -1
- package/dist/notifications/channel.js +0 -83
- package/dist/notifications/channel.js.map +0 -1
- package/dist/notifications/channels/adapter.js +0 -55
- package/dist/notifications/channels/adapter.js.map +0 -1
- package/dist/notifications/channels/index.js +0 -6
- package/dist/notifications/channels/index.js.map +0 -1
- package/dist/notifications/channels/log.js +0 -29
- package/dist/notifications/channels/log.js.map +0 -1
- package/dist/notifications/email.js +0 -72
- package/dist/notifications/email.js.map +0 -1
- package/dist/notifications/engine.js +0 -198
- package/dist/notifications/engine.js.map +0 -1
- package/dist/notifications/index.js +0 -24
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/phone.js +0 -48
- package/dist/notifications/phone.js.map +0 -1
- package/dist/notifications/sms.js +0 -65
- package/dist/notifications/sms.js.map +0 -1
- package/dist/notifications/types.js +0 -14
- package/dist/notifications/types.js.map +0 -1
- package/dist/notifications/webhook.js +0 -65
- package/dist/notifications/webhook.js.map +0 -1
- package/dist/resend/inbox.js +0 -199
- package/dist/resend/inbox.js.map +0 -1
- package/dist/resend/webhooks.js +0 -244
- package/dist/resend/webhooks.js.map +0 -1
- package/dist/search/browse.js +0 -225
- package/dist/search/browse.js.map +0 -1
- package/dist/search/perplexity.js +0 -41
- package/dist/search/perplexity.js.map +0 -1
- package/dist/slack/channels.js +0 -277
- package/dist/slack/channels.js.map +0 -1
- package/dist/slack/client.js +0 -468
- package/dist/slack/client.js.map +0 -1
- package/dist/slack/retry.js +0 -100
- package/dist/slack/retry.js.map +0 -1
- package/dist/slack/types.js +0 -52
- package/dist/slack/types.js.map +0 -1
- package/dist/slack/webhooks.js +0 -285
- package/dist/slack/webhooks.js.map +0 -1
- package/dist/stt/client.js +0 -66
- package/dist/stt/client.js.map +0 -1
- package/dist/stt/sidecar.js +0 -115
- package/dist/stt/sidecar.js.map +0 -1
- package/dist/tracing/bridge.js +0 -70
- package/dist/tracing/bridge.js.map +0 -1
- package/dist/tracing/correlation.js +0 -49
- package/dist/tracing/correlation.js.map +0 -1
- package/dist/tracing/index.js +0 -18
- package/dist/tracing/index.js.map +0 -1
- package/dist/tracing/init.js +0 -81
- package/dist/tracing/init.js.map +0 -1
- package/dist/tracing/instrument.js +0 -145
- package/dist/tracing/instrument.js.map +0 -1
- package/dist/tracing/middleware.js +0 -69
- package/dist/tracing/middleware.js.map +0 -1
- package/dist/tracing/tracer.js +0 -327
- package/dist/tracing/tracer.js.map +0 -1
- package/dist/tts/client.js +0 -48
- package/dist/tts/client.js.map +0 -1
- package/dist/tts/sidecar.js +0 -148
- package/dist/tts/sidecar.js.map +0 -1
- package/dist/twilio/call.js +0 -79
- package/dist/twilio/call.js.map +0 -1
- package/dist/vault/matcher.js +0 -197
- package/dist/vault/matcher.js.map +0 -1
- package/dist/vault/personal.js +0 -163
- package/dist/vault/personal.js.map +0 -1
- package/dist/vault/policy.js +0 -159
- package/dist/vault/policy.js.map +0 -1
- package/dist/vault/store.js +0 -122
- package/dist/vault/store.js.map +0 -1
- package/dist/vault/transfer.js +0 -188
- package/dist/vault/transfer.js.map +0 -1
- package/dist/volumes/index.js +0 -2
- package/dist/volumes/index.js.map +0 -1
- package/dist/volumes/manager.js +0 -462
- package/dist/volumes/manager.js.map +0 -1
- package/dist/volumes/types.js +0 -8
- package/dist/volumes/types.js.map +0 -1
- package/dist/webhooks/config.js +0 -214
- package/dist/webhooks/config.js.map +0 -1
- package/dist/webhooks/event-log.js +0 -132
- package/dist/webhooks/event-log.js.map +0 -1
- package/dist/webhooks/handler.js +0 -103
- package/dist/webhooks/handler.js.map +0 -1
- package/dist/webhooks/handlers.js +0 -231
- package/dist/webhooks/handlers.js.map +0 -1
- package/dist/webhooks/index.js +0 -33
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/mount.js +0 -400
- package/dist/webhooks/mount.js.map +0 -1
- package/dist/webhooks/registry.js +0 -143
- package/dist/webhooks/registry.js.map +0 -1
- package/dist/webhooks/relay.js +0 -53
- package/dist/webhooks/relay.js.map +0 -1
- package/dist/webhooks/retry.js +0 -270
- package/dist/webhooks/retry.js.map +0 -1
- package/dist/webhooks/router.js +0 -290
- package/dist/webhooks/router.js.map +0 -1
- package/dist/webhooks/twilio.js +0 -129
- package/dist/webhooks/twilio.js.map +0 -1
- package/dist/webhooks/types.js +0 -8
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/verify.js +0 -154
- package/dist/webhooks/verify.js.map +0 -1
|
@@ -2,49 +2,135 @@
|
|
|
2
2
|
* Brain document finder — auto-detects document references in user messages
|
|
3
3
|
* and resolves them to actual brain files.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Three search modes (in priority order):
|
|
6
|
+
* 1. RAG semantic search — fast, uses pre-computed embeddings
|
|
7
|
+
* 2. Filename/path match — keyword scoring on filenames and directories
|
|
8
|
+
* 3. Keyword content scan — REMOVED (replaced by RAG)
|
|
9
|
+
*
|
|
10
|
+
* Returns best matching file + sibling listing (option B from spec).
|
|
8
11
|
*/
|
|
9
12
|
import { readdir } from "node:fs/promises";
|
|
10
|
-
import { join, basename } from "node:path";
|
|
13
|
+
import { join, basename, dirname } from "node:path";
|
|
11
14
|
import { readBrainFile } from "../lib/brain-io.js";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
import { createLogger } from "../utils/logger.js";
|
|
16
|
+
const log = createLogger("brain-docs");
|
|
17
|
+
// ── Module-level RAG reference (set during server init) ──────────────────────
|
|
18
|
+
let _rag = null;
|
|
19
|
+
/** Wire the BrainRAG instance. Called once during server startup. */
|
|
20
|
+
export function setBrainRAG(rag) {
|
|
21
|
+
_rag = rag;
|
|
22
|
+
}
|
|
23
|
+
// ── Patterns ─────────────────────────────────────────────────────────────────
|
|
24
|
+
/** Explicit document reference — "read my paper", "show the draft", etc. */
|
|
25
|
+
const DOC_REF_PATTERN = /\b(read|show|open|pull up|find|get|load|look at|check)\b.*\b(paper|draft|doc|document|note|post|thread|whitepaper|positioning|writeup|write-?up|article|research|report|book|chapter|spec)\b/i;
|
|
26
|
+
/** Question about brain knowledge — "which book", "what does X say", "where is the" */
|
|
27
|
+
const KNOWLEDGE_QUESTION_PATTERN = /\b(which|what|where|how|did|does|do|have|is|are|tell me|remind me)\b.*\b(book|chapter|spec|paper|draft|note|plan|goal|roadmap|decision|protocol|template|principle|identity|series|write|wrote|writing|document|research|finance|govern)\b/i;
|
|
28
|
+
// ── Keyword extraction ───────────────────────────────────────────────────────
|
|
26
29
|
function extractKeywords(message) {
|
|
27
30
|
const stopWords = new Set([
|
|
28
31
|
"the", "a", "an", "my", "our", "that", "this", "it", "its",
|
|
29
32
|
"read", "show", "open", "pull", "up", "find", "get", "load",
|
|
30
33
|
"look", "at", "check", "can", "you", "me", "for", "about",
|
|
31
34
|
"please", "and", "or", "in", "on", "to", "of", "with",
|
|
35
|
+
"which", "what", "where", "how", "did", "does", "have",
|
|
36
|
+
"is", "are", "tell", "remind", "we", "were", "was", "been",
|
|
37
|
+
"do", "not", "but", "from", "who", "they",
|
|
32
38
|
]);
|
|
33
|
-
|
|
39
|
+
const tokens = message
|
|
34
40
|
.toLowerCase()
|
|
35
41
|
.replace(/[^a-z0-9\s-]/g, " ")
|
|
36
42
|
.split(/\s+/)
|
|
37
|
-
.filter(
|
|
43
|
+
.filter(Boolean);
|
|
44
|
+
const keywords = [];
|
|
45
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
46
|
+
const t = tokens[i];
|
|
47
|
+
if (/^\d+$/.test(t)) {
|
|
48
|
+
keywords.push(t);
|
|
49
|
+
if (i > 0 && keywords.length >= 2) {
|
|
50
|
+
const prev = keywords[keywords.length - 2];
|
|
51
|
+
if (!/^\d+$/.test(prev)) {
|
|
52
|
+
keywords.push(prev + t);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (t.length > 2 && !stopWords.has(t)) {
|
|
57
|
+
keywords.push(t);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return keywords;
|
|
38
61
|
}
|
|
62
|
+
// ── Main search ──────────────────────────────────────────────────────────────
|
|
39
63
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
64
|
+
* Search brain files for the best match to the user's message.
|
|
65
|
+
*
|
|
66
|
+
* Priority:
|
|
67
|
+
* 1. RAG semantic search (if available and indexed)
|
|
68
|
+
* 2. Keyword filename match (fallback)
|
|
42
69
|
*/
|
|
43
|
-
function
|
|
70
|
+
export async function findBrainDocument(message) {
|
|
71
|
+
const keywords = extractKeywords(message);
|
|
72
|
+
const docMatch = DOC_REF_PATTERN.test(message);
|
|
73
|
+
const knowledgeMatch = KNOWLEDGE_QUESTION_PATTERN.test(message);
|
|
74
|
+
log.info(`findBrainDocument: keywords=[${keywords.join(",")}] docRef=${docMatch} knowledgeQ=${knowledgeMatch}`);
|
|
75
|
+
if (!docMatch && !knowledgeMatch) {
|
|
76
|
+
log.info("No pattern matched — skipping brain doc search");
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
// ── Mode 1: RAG semantic search ──────────────────────────────────────────
|
|
80
|
+
if (_rag && _rag.ready) {
|
|
81
|
+
try {
|
|
82
|
+
log.info("Trying RAG semantic search...");
|
|
83
|
+
const results = await _rag.query(message, 5);
|
|
84
|
+
if (results.length > 0) {
|
|
85
|
+
const best = results[0];
|
|
86
|
+
log.info(`RAG hit: ${best.filePath} (score: ${best.score.toFixed(3)})${best.siblings ? `, ${best.siblings.length} siblings` : ""}`);
|
|
87
|
+
const content = await readBrainFile(best.fullPath);
|
|
88
|
+
const filename = basename(best.filePath);
|
|
89
|
+
// Build sibling listing
|
|
90
|
+
let siblings;
|
|
91
|
+
if (best.siblings && best.siblings.length > 0) {
|
|
92
|
+
siblings = best.siblings;
|
|
93
|
+
}
|
|
94
|
+
return { path: best.fullPath, filename, content, siblings };
|
|
95
|
+
}
|
|
96
|
+
log.info("RAG returned no results above threshold");
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
log.error("RAG search failed, falling back to keyword match", {
|
|
100
|
+
error: err instanceof Error ? err.message : String(err),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
log.info("RAG not available, using keyword fallback");
|
|
106
|
+
}
|
|
107
|
+
// ── Mode 2: Keyword filename match (fallback) ───────────────────────────
|
|
108
|
+
if (keywords.length === 0)
|
|
109
|
+
return null;
|
|
110
|
+
return keywordFilenameSearch(keywords);
|
|
111
|
+
}
|
|
112
|
+
// ── Keyword filename fallback ────────────────────────────────────────────────
|
|
113
|
+
import { stat as fsStat } from "node:fs/promises";
|
|
114
|
+
import { FILES_DIR, resolveBrainDir } from "../lib/paths.js";
|
|
115
|
+
const DOC_DIRS = [
|
|
116
|
+
FILES_DIR,
|
|
117
|
+
resolveBrainDir("content"),
|
|
118
|
+
resolveBrainDir("knowledge"),
|
|
119
|
+
resolveBrainDir("identity"),
|
|
120
|
+
resolveBrainDir("operations"),
|
|
121
|
+
resolveBrainDir("skills"),
|
|
122
|
+
resolveBrainDir("templates"),
|
|
123
|
+
];
|
|
124
|
+
const SEARCHABLE_EXTS = new Set([".md", ".yaml", ".yml", ".txt", ".json"]);
|
|
125
|
+
const SKIP_DIRS = new Set([
|
|
126
|
+
"node_modules", ".git", ".obsidian", "logs", "tasks",
|
|
127
|
+
"daily", "hourly", "memory", "ops", "metrics", "ledger",
|
|
128
|
+
]);
|
|
129
|
+
function scoreFilename(filename, keywords) {
|
|
44
130
|
const parts = basename(filename, ".md")
|
|
45
131
|
.toLowerCase()
|
|
46
132
|
.split(/[-_.]/)
|
|
47
|
-
.filter((p) => p.length >
|
|
133
|
+
.filter((p) => p.length > 0);
|
|
48
134
|
let score = 0;
|
|
49
135
|
for (const kw of keywords) {
|
|
50
136
|
for (const part of parts) {
|
|
@@ -54,46 +140,78 @@ function scoreMatch(filename, keywords) {
|
|
|
54
140
|
}
|
|
55
141
|
return score;
|
|
56
142
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
export async function findBrainDocument(message) {
|
|
62
|
-
// Only trigger on messages that reference a document
|
|
63
|
-
if (!DOC_REF_PATTERN.test(message))
|
|
64
|
-
return null;
|
|
65
|
-
const keywords = extractKeywords(message);
|
|
66
|
-
if (keywords.length === 0)
|
|
67
|
-
return null;
|
|
68
|
-
// Scan all doc directories, collect candidates
|
|
69
|
-
const candidates = [];
|
|
70
|
-
for (const dir of DOC_DIRS) {
|
|
143
|
+
async function collectFiles(dir) {
|
|
144
|
+
const results = [];
|
|
145
|
+
async function walk(d) {
|
|
146
|
+
let entries;
|
|
71
147
|
try {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
148
|
+
entries = await readdir(d);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
for (const name of entries) {
|
|
154
|
+
if (name.startsWith(".") && name !== ".config")
|
|
155
|
+
continue;
|
|
156
|
+
if (SKIP_DIRS.has(name))
|
|
157
|
+
continue;
|
|
158
|
+
const full = join(d, name);
|
|
159
|
+
try {
|
|
160
|
+
const s = await fsStat(full);
|
|
161
|
+
if (s.isDirectory()) {
|
|
162
|
+
await walk(full);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const ext = name.substring(name.lastIndexOf(".")).toLowerCase();
|
|
166
|
+
if (SEARCHABLE_EXTS.has(ext) && s.size < 500_000) {
|
|
167
|
+
results.push({ path: full, filename: name });
|
|
168
|
+
}
|
|
79
169
|
}
|
|
80
170
|
}
|
|
171
|
+
catch {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
81
174
|
}
|
|
82
|
-
|
|
83
|
-
|
|
175
|
+
}
|
|
176
|
+
await walk(dir);
|
|
177
|
+
return results;
|
|
178
|
+
}
|
|
179
|
+
async function keywordFilenameSearch(keywords) {
|
|
180
|
+
const candidates = [];
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
for (const dir of DOC_DIRS) {
|
|
183
|
+
if (seen.has(dir))
|
|
184
|
+
continue;
|
|
185
|
+
seen.add(dir);
|
|
186
|
+
const files = await collectFiles(dir);
|
|
187
|
+
for (const file of files) {
|
|
188
|
+
const parentDir = basename(dirname(file.path));
|
|
189
|
+
const score = scoreFilename(file.filename, keywords) + scoreFilename(parentDir, keywords);
|
|
190
|
+
if (score > 0) {
|
|
191
|
+
candidates.push({ ...file, score });
|
|
192
|
+
}
|
|
84
193
|
}
|
|
85
194
|
}
|
|
86
195
|
if (candidates.length === 0)
|
|
87
196
|
return null;
|
|
88
|
-
// Sort by score descending, take the best match
|
|
89
197
|
candidates.sort((a, b) => b.score - a.score);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (best.score < 2)
|
|
198
|
+
log.info(`Keyword fallback: ${candidates.length} candidates, best: ${candidates[0].filename} (score: ${candidates[0].score})`);
|
|
199
|
+
if (candidates[0].score < 2)
|
|
93
200
|
return null;
|
|
94
201
|
try {
|
|
202
|
+
const best = candidates[0];
|
|
95
203
|
const content = await readBrainFile(best.path);
|
|
96
|
-
|
|
204
|
+
// Sibling listing
|
|
205
|
+
const dir = dirname(best.path);
|
|
206
|
+
let siblings;
|
|
207
|
+
try {
|
|
208
|
+
const entries = await readdir(dir);
|
|
209
|
+
const sibs = entries.filter((e) => e !== best.filename);
|
|
210
|
+
if (sibs.length > 0)
|
|
211
|
+
siblings = sibs;
|
|
212
|
+
}
|
|
213
|
+
catch { /* ignore */ }
|
|
214
|
+
return { path: best.path, filename: best.filename, content, siblings };
|
|
97
215
|
}
|
|
98
216
|
catch {
|
|
99
217
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brain-docs.js","sourceRoot":"","sources":["../../src/search/brain-docs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"brain-docs.js","sourceRoot":"","sources":["../../src/search/brain-docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain RAG — semantic retrieval for brain files.
|
|
3
|
+
*
|
|
4
|
+
* Indexes brain files into chunks with Ollama embeddings.
|
|
5
|
+
* Stores in brain/memory/file-embeddings.jsonl (append-only).
|
|
6
|
+
* In-memory cosine similarity search over chunk vectors.
|
|
7
|
+
*
|
|
8
|
+
* The vector index is a derived cache. Delete the file, re-index from brain.
|
|
9
|
+
*/
|
|
10
|
+
export interface RAGResult {
|
|
11
|
+
filePath: string;
|
|
12
|
+
heading: string;
|
|
13
|
+
chunk: string;
|
|
14
|
+
score: number;
|
|
15
|
+
fullPath: string;
|
|
16
|
+
/** Other files in the same directory (sibling listing for option B) */
|
|
17
|
+
siblings?: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare class BrainRAG {
|
|
20
|
+
private chunks;
|
|
21
|
+
/** Track mtime per file so we know what's stale */
|
|
22
|
+
private fileMtimes;
|
|
23
|
+
private embeddingsPath;
|
|
24
|
+
private _ready;
|
|
25
|
+
constructor();
|
|
26
|
+
get ready(): boolean;
|
|
27
|
+
/** Load existing embeddings from disk. Fast — no Ollama needed. */
|
|
28
|
+
load(): Promise<void>;
|
|
29
|
+
/** Full index: scan all brain files, chunk and embed anything new or changed. */
|
|
30
|
+
indexAll(): Promise<{
|
|
31
|
+
indexed: number;
|
|
32
|
+
skipped: number;
|
|
33
|
+
errors: number;
|
|
34
|
+
}>;
|
|
35
|
+
/** Read file content, handling PDFs (text and scanned) specially. */
|
|
36
|
+
private readFileContent;
|
|
37
|
+
/** Index a single file: chunk, embed, persist. */
|
|
38
|
+
indexFile(filePath: string): Promise<void>;
|
|
39
|
+
/** Semantic search: embed query, return top-k file chunks with scores. */
|
|
40
|
+
query(text: string, topK?: number): Promise<RAGResult[]>;
|
|
41
|
+
/** Force re-index: clear in-memory state and rebuild from files. */
|
|
42
|
+
reindex(): Promise<void>;
|
|
43
|
+
private collectFiles;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=brain-rag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-rag.d.ts","sourceRoot":"","sources":["../../src/search/brain-rag.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4DH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAkC;IAChD,mDAAmD;IACnD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAS;;IAMvB,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,mEAAmE;IAC7D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B3B,iFAAiF;IAC3E,QAAQ,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IA0C/E,qEAAqE;YACvD,eAAe;IAsB7B,kDAAkD;IAC5C,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4ChD,0EAA0E;IACpE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAoDzD,oEAAoE;IAC9D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAQhB,YAAY;CA2B3B"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain RAG — semantic retrieval for brain files.
|
|
3
|
+
*
|
|
4
|
+
* Indexes brain files into chunks with Ollama embeddings.
|
|
5
|
+
* Stores in brain/memory/file-embeddings.jsonl (append-only).
|
|
6
|
+
* In-memory cosine similarity search over chunk vectors.
|
|
7
|
+
*
|
|
8
|
+
* The vector index is a derived cache. Delete the file, re-index from brain.
|
|
9
|
+
*/
|
|
10
|
+
import { join, relative, basename, dirname } from "node:path";
|
|
11
|
+
import { readdir, stat } from "node:fs/promises";
|
|
12
|
+
import { createLogger } from "../utils/logger.js";
|
|
13
|
+
import { readBrainFile, readBrainLines, appendBrainLine } from "../lib/brain-io.js";
|
|
14
|
+
import { BRAIN_DIR, FILES_DIR, resolveBrainDir } from "../lib/paths.js";
|
|
15
|
+
import { embed, embedBatch, isOllamaAvailable, cosine } from "./embedder.js";
|
|
16
|
+
import { chunkMarkdown } from "./chunker.js";
|
|
17
|
+
import { readFile } from "node:fs/promises";
|
|
18
|
+
import { extractPdfText, extractImageText } from "../files/extract.js";
|
|
19
|
+
const log = createLogger("brain-rag");
|
|
20
|
+
const FILE_EMBEDDINGS = "file-embeddings.jsonl";
|
|
21
|
+
const BATCH_SIZE = 10;
|
|
22
|
+
const SEARCHABLE_EXTS = new Set([".md", ".yaml", ".yml", ".txt", ".pdf"]);
|
|
23
|
+
const SKIP_DIRS = new Set([
|
|
24
|
+
"node_modules", ".git", ".obsidian", "logs", "tasks",
|
|
25
|
+
"daily", "hourly", "memory", "ops", "metrics", "ledger",
|
|
26
|
+
".config",
|
|
27
|
+
]);
|
|
28
|
+
const MAX_FILE_SIZE = 500_000; // 500KB
|
|
29
|
+
/** Directories to scan for brain files. */
|
|
30
|
+
const SCAN_DIRS = [
|
|
31
|
+
FILES_DIR,
|
|
32
|
+
resolveBrainDir("content"),
|
|
33
|
+
resolveBrainDir("knowledge"),
|
|
34
|
+
resolveBrainDir("identity"),
|
|
35
|
+
resolveBrainDir("operations"),
|
|
36
|
+
resolveBrainDir("skills"),
|
|
37
|
+
resolveBrainDir("templates"),
|
|
38
|
+
];
|
|
39
|
+
// ── BrainRAG class ───────────────────────────────────────────────────────────
|
|
40
|
+
export class BrainRAG {
|
|
41
|
+
chunks = new Map();
|
|
42
|
+
/** Track mtime per file so we know what's stale */
|
|
43
|
+
fileMtimes = new Map();
|
|
44
|
+
embeddingsPath;
|
|
45
|
+
_ready = false;
|
|
46
|
+
constructor() {
|
|
47
|
+
this.embeddingsPath = join(BRAIN_DIR, "memory", FILE_EMBEDDINGS);
|
|
48
|
+
}
|
|
49
|
+
get ready() {
|
|
50
|
+
return this._ready;
|
|
51
|
+
}
|
|
52
|
+
/** Load existing embeddings from disk. Fast — no Ollama needed. */
|
|
53
|
+
async load() {
|
|
54
|
+
const lines = await readBrainLines(this.embeddingsPath);
|
|
55
|
+
let loaded = 0;
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
try {
|
|
58
|
+
const entry = JSON.parse(line);
|
|
59
|
+
if (!entry.id || !entry.v)
|
|
60
|
+
continue;
|
|
61
|
+
// Last-write-wins: later lines for same ID supersede earlier
|
|
62
|
+
this.chunks.set(entry.id, {
|
|
63
|
+
id: entry.id,
|
|
64
|
+
filePath: entry.filePath,
|
|
65
|
+
heading: entry.heading,
|
|
66
|
+
index: entry.index,
|
|
67
|
+
mtime: entry.mtime,
|
|
68
|
+
vec: new Float32Array(entry.v),
|
|
69
|
+
});
|
|
70
|
+
// Track highest mtime per file
|
|
71
|
+
const existing = this.fileMtimes.get(entry.filePath) ?? 0;
|
|
72
|
+
if (entry.mtime > existing)
|
|
73
|
+
this.fileMtimes.set(entry.filePath, entry.mtime);
|
|
74
|
+
loaded++;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this._ready = true;
|
|
81
|
+
if (loaded > 0)
|
|
82
|
+
log.info(`Loaded ${this.chunks.size} chunk embeddings from disk`);
|
|
83
|
+
}
|
|
84
|
+
/** Full index: scan all brain files, chunk and embed anything new or changed. */
|
|
85
|
+
async indexAll() {
|
|
86
|
+
const available = await isOllamaAvailable();
|
|
87
|
+
if (!available) {
|
|
88
|
+
log.info("Ollama unavailable — skipping file indexing");
|
|
89
|
+
return { indexed: 0, skipped: 0, errors: 0 };
|
|
90
|
+
}
|
|
91
|
+
let indexed = 0;
|
|
92
|
+
let skipped = 0;
|
|
93
|
+
let errors = 0;
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
for (const dir of SCAN_DIRS) {
|
|
96
|
+
if (seen.has(dir))
|
|
97
|
+
continue;
|
|
98
|
+
seen.add(dir);
|
|
99
|
+
const files = await this.collectFiles(dir);
|
|
100
|
+
for (const file of files) {
|
|
101
|
+
try {
|
|
102
|
+
const relPath = relative(BRAIN_DIR, file.path).replace(/\\/g, "/");
|
|
103
|
+
const existingMtime = this.fileMtimes.get(relPath) ?? 0;
|
|
104
|
+
if (file.mtime <= existingMtime) {
|
|
105
|
+
skipped++;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
await this.indexFile(file.path);
|
|
109
|
+
indexed++;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
errors++;
|
|
113
|
+
log.error(`Failed to index ${file.path}`, {
|
|
114
|
+
error: err instanceof Error ? err.message : String(err),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
log.info(`Index complete: ${indexed} indexed, ${skipped} skipped, ${errors} errors (${this.chunks.size} total chunks)`);
|
|
120
|
+
return { indexed, skipped, errors };
|
|
121
|
+
}
|
|
122
|
+
/** Read file content, handling PDFs (text and scanned) specially. */
|
|
123
|
+
async readFileContent(filePath) {
|
|
124
|
+
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
125
|
+
if (ext === ".pdf") {
|
|
126
|
+
const buffer = Buffer.from(await readFile(filePath));
|
|
127
|
+
// Try text extraction first
|
|
128
|
+
let text = await extractPdfText(buffer);
|
|
129
|
+
// If PDF is scanned (no extractable text), fall back to OCR
|
|
130
|
+
if (!text.trim() || text.trim().length < 50) {
|
|
131
|
+
try {
|
|
132
|
+
log.info(`PDF appears scanned, trying OCR: ${basename(filePath)}`);
|
|
133
|
+
text = await extractImageText(buffer);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
log.warn(`OCR failed for ${basename(filePath)}`, {
|
|
137
|
+
error: err instanceof Error ? err.message : String(err),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return text;
|
|
142
|
+
}
|
|
143
|
+
return readBrainFile(filePath);
|
|
144
|
+
}
|
|
145
|
+
/** Index a single file: chunk, embed, persist. */
|
|
146
|
+
async indexFile(filePath) {
|
|
147
|
+
const relPath = relative(BRAIN_DIR, filePath).replace(/\\/g, "/");
|
|
148
|
+
const content = await this.readFileContent(filePath);
|
|
149
|
+
const fileStat = await stat(filePath);
|
|
150
|
+
const mtime = fileStat.mtimeMs;
|
|
151
|
+
const fileChunks = chunkMarkdown(relPath, content);
|
|
152
|
+
if (fileChunks.length === 0)
|
|
153
|
+
return;
|
|
154
|
+
// Embed in batches
|
|
155
|
+
for (let i = 0; i < fileChunks.length; i += BATCH_SIZE) {
|
|
156
|
+
const batch = fileChunks.slice(i, i + BATCH_SIZE);
|
|
157
|
+
const texts = batch.map((c) => c.text);
|
|
158
|
+
const vecs = await embedBatch(texts);
|
|
159
|
+
for (let j = 0; j < batch.length; j++) {
|
|
160
|
+
const chunk = batch[j];
|
|
161
|
+
const record = {
|
|
162
|
+
id: chunk.id,
|
|
163
|
+
filePath: relPath,
|
|
164
|
+
heading: chunk.heading,
|
|
165
|
+
index: chunk.index,
|
|
166
|
+
mtime,
|
|
167
|
+
vec: vecs[j],
|
|
168
|
+
};
|
|
169
|
+
this.chunks.set(chunk.id, record);
|
|
170
|
+
// Persist
|
|
171
|
+
const line = {
|
|
172
|
+
id: chunk.id,
|
|
173
|
+
filePath: relPath,
|
|
174
|
+
heading: chunk.heading,
|
|
175
|
+
index: chunk.index,
|
|
176
|
+
mtime,
|
|
177
|
+
v: Array.from(vecs[j]),
|
|
178
|
+
};
|
|
179
|
+
await appendBrainLine(this.embeddingsPath, JSON.stringify(line));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
this.fileMtimes.set(relPath, mtime);
|
|
183
|
+
log.info(`Indexed ${relPath}: ${fileChunks.length} chunks`);
|
|
184
|
+
}
|
|
185
|
+
/** Semantic search: embed query, return top-k file chunks with scores. */
|
|
186
|
+
async query(text, topK = 5) {
|
|
187
|
+
if (this.chunks.size === 0)
|
|
188
|
+
return [];
|
|
189
|
+
const queryVec = await embed(text);
|
|
190
|
+
const scored = [];
|
|
191
|
+
for (const record of this.chunks.values()) {
|
|
192
|
+
const score = cosine(queryVec, record.vec);
|
|
193
|
+
scored.push({ record, score });
|
|
194
|
+
}
|
|
195
|
+
scored.sort((a, b) => b.score - a.score);
|
|
196
|
+
const topResults = scored.slice(0, topK);
|
|
197
|
+
const results = [];
|
|
198
|
+
for (const { record, score } of topResults) {
|
|
199
|
+
if (score < 0.3)
|
|
200
|
+
continue; // threshold
|
|
201
|
+
const fullPath = join(BRAIN_DIR, record.filePath);
|
|
202
|
+
// Option B: sibling listing
|
|
203
|
+
const dir = dirname(fullPath);
|
|
204
|
+
let siblings;
|
|
205
|
+
try {
|
|
206
|
+
const entries = await readdir(dir);
|
|
207
|
+
const sibs = entries.filter((e) => e !== basename(record.filePath));
|
|
208
|
+
if (sibs.length > 0)
|
|
209
|
+
siblings = sibs;
|
|
210
|
+
}
|
|
211
|
+
catch { /* ignore */ }
|
|
212
|
+
results.push({
|
|
213
|
+
filePath: record.filePath,
|
|
214
|
+
heading: record.heading,
|
|
215
|
+
chunk: "", // caller reads full file; chunk text not persisted
|
|
216
|
+
score,
|
|
217
|
+
fullPath,
|
|
218
|
+
siblings,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// Deduplicate by filePath — keep highest score per file
|
|
222
|
+
const byFile = new Map();
|
|
223
|
+
for (const r of results) {
|
|
224
|
+
const existing = byFile.get(r.filePath);
|
|
225
|
+
if (!existing || r.score > existing.score) {
|
|
226
|
+
byFile.set(r.filePath, r);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return Array.from(byFile.values()).sort((a, b) => b.score - a.score);
|
|
230
|
+
}
|
|
231
|
+
/** Force re-index: clear in-memory state and rebuild from files. */
|
|
232
|
+
async reindex() {
|
|
233
|
+
this.chunks.clear();
|
|
234
|
+
this.fileMtimes.clear();
|
|
235
|
+
await this.indexAll();
|
|
236
|
+
}
|
|
237
|
+
// ── File collection ──────────────────────────────────────────────────────
|
|
238
|
+
async collectFiles(dir) {
|
|
239
|
+
const results = [];
|
|
240
|
+
const walk = async (d) => {
|
|
241
|
+
let entries;
|
|
242
|
+
try {
|
|
243
|
+
entries = await readdir(d);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
for (const name of entries) {
|
|
249
|
+
if (name.startsWith("."))
|
|
250
|
+
continue;
|
|
251
|
+
if (SKIP_DIRS.has(name))
|
|
252
|
+
continue;
|
|
253
|
+
const full = join(d, name);
|
|
254
|
+
try {
|
|
255
|
+
const s = await stat(full);
|
|
256
|
+
if (s.isDirectory()) {
|
|
257
|
+
await walk(full);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
const ext = name.substring(name.lastIndexOf(".")).toLowerCase();
|
|
261
|
+
if (SEARCHABLE_EXTS.has(ext) && s.size < MAX_FILE_SIZE) {
|
|
262
|
+
results.push({ path: full, mtime: s.mtimeMs });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
await walk(dir);
|
|
272
|
+
return results;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=brain-rag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-rag.js","sourceRoot":"","sources":["../../src/search/brain-rag.ts"],"names":[],"mappings":"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"}
|