@kybernesis/brain-core 0.1.0
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/dist/claude-call.d.ts +37 -0
- package/dist/claude-call.d.ts.map +1 -0
- package/dist/claude-call.js +55 -0
- package/dist/claude-call.js.map +1 -0
- package/dist/entity-graph.d.ts +79 -0
- package/dist/entity-graph.d.ts.map +1 -0
- package/dist/entity-graph.js +611 -0
- package/dist/entity-graph.js.map +1 -0
- package/dist/fact-contradiction.d.ts +25 -0
- package/dist/fact-contradiction.d.ts.map +1 -0
- package/dist/fact-contradiction.js +109 -0
- package/dist/fact-contradiction.js.map +1 -0
- package/dist/fact-extractor.d.ts +26 -0
- package/dist/fact-extractor.d.ts.map +1 -0
- package/dist/fact-extractor.js +98 -0
- package/dist/fact-extractor.js.map +1 -0
- package/dist/fact-retrieval.d.ts +51 -0
- package/dist/fact-retrieval.d.ts.map +1 -0
- package/dist/fact-retrieval.js +401 -0
- package/dist/fact-retrieval.js.map +1 -0
- package/dist/fact-store.d.ts +26 -0
- package/dist/fact-store.d.ts.map +1 -0
- package/dist/fact-store.js +181 -0
- package/dist/fact-store.js.map +1 -0
- package/dist/fact-temporal.d.ts +20 -0
- package/dist/fact-temporal.d.ts.map +1 -0
- package/dist/fact-temporal.js +79 -0
- package/dist/fact-temporal.js.map +1 -0
- package/dist/fts-sanitizer.d.ts +32 -0
- package/dist/fts-sanitizer.d.ts.map +1 -0
- package/dist/fts-sanitizer.js +61 -0
- package/dist/fts-sanitizer.js.map +1 -0
- package/dist/hybrid-search.d.ts +44 -0
- package/dist/hybrid-search.d.ts.map +1 -0
- package/dist/hybrid-search.js +410 -0
- package/dist/hybrid-search.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/ops.d.ts +28 -0
- package/dist/ops.d.ts.map +1 -0
- package/dist/ops.js +307 -0
- package/dist/ops.js.map +1 -0
- package/dist/queue.d.ts +13 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +28 -0
- package/dist/queue.js.map +1 -0
- package/dist/relationship-extractor.d.ts +38 -0
- package/dist/relationship-extractor.d.ts.map +1 -0
- package/dist/relationship-extractor.js +119 -0
- package/dist/relationship-extractor.js.map +1 -0
- package/dist/sleep/config.d.ts +47 -0
- package/dist/sleep/config.d.ts.map +1 -0
- package/dist/sleep/config.js +46 -0
- package/dist/sleep/config.js.map +1 -0
- package/dist/sleep/db.d.ts +16 -0
- package/dist/sleep/db.d.ts.map +1 -0
- package/dist/sleep/db.js +114 -0
- package/dist/sleep/db.js.map +1 -0
- package/dist/sleep/index.d.ts +69 -0
- package/dist/sleep/index.d.ts.map +1 -0
- package/dist/sleep/index.js +99 -0
- package/dist/sleep/index.js.map +1 -0
- package/dist/sleep/steps/consolidate.d.ts +19 -0
- package/dist/sleep/steps/consolidate.d.ts.map +1 -0
- package/dist/sleep/steps/consolidate.js +74 -0
- package/dist/sleep/steps/consolidate.js.map +1 -0
- package/dist/sleep/steps/decay.d.ts +19 -0
- package/dist/sleep/steps/decay.d.ts.map +1 -0
- package/dist/sleep/steps/decay.js +121 -0
- package/dist/sleep/steps/decay.js.map +1 -0
- package/dist/sleep/steps/entity-hygiene.d.ts +29 -0
- package/dist/sleep/steps/entity-hygiene.d.ts.map +1 -0
- package/dist/sleep/steps/entity-hygiene.js +452 -0
- package/dist/sleep/steps/entity-hygiene.js.map +1 -0
- package/dist/sleep/steps/link.d.ts +20 -0
- package/dist/sleep/steps/link.d.ts.map +1 -0
- package/dist/sleep/steps/link.js +216 -0
- package/dist/sleep/steps/link.js.map +1 -0
- package/dist/sleep/steps/observe.d.ts +17 -0
- package/dist/sleep/steps/observe.d.ts.map +1 -0
- package/dist/sleep/steps/observe.js +192 -0
- package/dist/sleep/steps/observe.js.map +1 -0
- package/dist/sleep/steps/profile.d.ts +15 -0
- package/dist/sleep/steps/profile.d.ts.map +1 -0
- package/dist/sleep/steps/profile.js +26 -0
- package/dist/sleep/steps/profile.js.map +1 -0
- package/dist/sleep/steps/reasoning.d.ts +19 -0
- package/dist/sleep/steps/reasoning.d.ts.map +1 -0
- package/dist/sleep/steps/reasoning.js +173 -0
- package/dist/sleep/steps/reasoning.js.map +1 -0
- package/dist/sleep/steps/summarize.d.ts +21 -0
- package/dist/sleep/steps/summarize.d.ts.map +1 -0
- package/dist/sleep/steps/summarize.js +206 -0
- package/dist/sleep/steps/summarize.js.map +1 -0
- package/dist/sleep/steps/tag.d.ts +16 -0
- package/dist/sleep/steps/tag.d.ts.map +1 -0
- package/dist/sleep/steps/tag.js +84 -0
- package/dist/sleep/steps/tag.js.map +1 -0
- package/dist/sleep/steps/tier.d.ts +18 -0
- package/dist/sleep/steps/tier.d.ts.map +1 -0
- package/dist/sleep/steps/tier.js +112 -0
- package/dist/sleep/steps/tier.js.map +1 -0
- package/dist/sleep/utils/checkpoint.d.ts +11 -0
- package/dist/sleep/utils/checkpoint.d.ts.map +1 -0
- package/dist/sleep/utils/checkpoint.js +26 -0
- package/dist/sleep/utils/checkpoint.js.map +1 -0
- package/dist/sleep/utils/jaccard.d.ts +7 -0
- package/dist/sleep/utils/jaccard.d.ts.map +1 -0
- package/dist/sleep/utils/jaccard.js +19 -0
- package/dist/sleep/utils/jaccard.js.map +1 -0
- package/dist/store-conversation.d.ts +29 -0
- package/dist/store-conversation.d.ts.map +1 -0
- package/dist/store-conversation.js +227 -0
- package/dist/store-conversation.js.map +1 -0
- package/dist/timeline.d.ts +50 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +389 -0
- package/dist/timeline.js.map +1 -0
- package/dist/user-profile.d.ts +30 -0
- package/dist/user-profile.d.ts.map +1 -0
- package/dist/user-profile.js +147 -0
- package/dist/user-profile.js.map +1 -0
- package/dist/vectors.d.ts +56 -0
- package/dist/vectors.d.ts.map +1 -0
- package/dist/vectors.js +132 -0
- package/dist/vectors.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fact-first retrieval engine — port of KAD's fact-retrieval.ts.
|
|
3
|
+
*
|
|
4
|
+
* 4-layer retrieval:
|
|
5
|
+
* Layer 1: Direct FTS5 + semantic search on facts
|
|
6
|
+
* Layer 2: Entity expansion (1-3 hop BFS graph traversal)
|
|
7
|
+
* Layer 2.5: Scene expansion + bridge discovery
|
|
8
|
+
* Layer 3: Supporting context (source conversation segments)
|
|
9
|
+
* Layer 4: Context optimization (prune to token budget, deduplicate)
|
|
10
|
+
*
|
|
11
|
+
* Bug Fix #2 applied here: uses sanitizeFtsQuery for all FTS MATCH calls.
|
|
12
|
+
* Bug Fix #9 applied here: wordMatchRatio denominator is FTS-query token count.
|
|
13
|
+
*/
|
|
14
|
+
import { getDb } from '@kybernesis/brain-storage-sqlite';
|
|
15
|
+
import { ensureFactsTable, getFactsForEntity } from './fact-store.js';
|
|
16
|
+
import { semanticSearch } from './vectors.js';
|
|
17
|
+
import { sanitizeFtsQuery } from './fts-sanitizer.js';
|
|
18
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
19
|
+
function estimateTokens(text) {
|
|
20
|
+
return Math.ceil(text.length / 4);
|
|
21
|
+
}
|
|
22
|
+
function wordOverlap(a, b) {
|
|
23
|
+
const wordsA = new Set(a.toLowerCase().split(/\s+/).filter(w => w.length >= 3));
|
|
24
|
+
const wordsB = new Set(b.toLowerCase().split(/\s+/).filter(w => w.length >= 3));
|
|
25
|
+
if (wordsA.size === 0 || wordsB.size === 0)
|
|
26
|
+
return 0;
|
|
27
|
+
let common = 0;
|
|
28
|
+
for (const w of wordsA) {
|
|
29
|
+
if (wordsB.has(w))
|
|
30
|
+
common++;
|
|
31
|
+
}
|
|
32
|
+
return common / Math.max(wordsA.size, wordsB.size);
|
|
33
|
+
}
|
|
34
|
+
// ─── Layer 1: Direct fact search ─────────────────────────────────────────────
|
|
35
|
+
async function searchFactsDirect(t, query, limit) {
|
|
36
|
+
await ensureFactsTable(t);
|
|
37
|
+
const db = getDb(t, 'timeline');
|
|
38
|
+
const results = [];
|
|
39
|
+
// Bug Fix #2: use sanitizeFtsQuery instead of naive replace
|
|
40
|
+
const sanitized = sanitizeFtsQuery(query);
|
|
41
|
+
// Bug Fix #9: derive score denominator from FTS token count, not raw query
|
|
42
|
+
const ftsTokens = sanitized
|
|
43
|
+
? sanitized.split(' OR ').map(t => t.replace(/^"|"$/g, '').toLowerCase()).filter(Boolean)
|
|
44
|
+
: [];
|
|
45
|
+
if (sanitized) {
|
|
46
|
+
try {
|
|
47
|
+
const ftsRows = db.prepare(`
|
|
48
|
+
SELECT f.id, f.content, f.category, f.confidence, f.timestamp,
|
|
49
|
+
f.entities_json, f.is_latest, f.expires_at, f.source_conversation_id
|
|
50
|
+
FROM facts f
|
|
51
|
+
JOIN facts_fts fts ON f.id = fts.rowid
|
|
52
|
+
WHERE facts_fts MATCH ?
|
|
53
|
+
AND COALESCE(f.is_latest, 1) = 1
|
|
54
|
+
AND (f.expires_at IS NULL OR f.expires_at > datetime('now'))
|
|
55
|
+
ORDER BY rank
|
|
56
|
+
LIMIT ?
|
|
57
|
+
`).all(sanitized, limit * 2);
|
|
58
|
+
for (const row of ftsRows) {
|
|
59
|
+
const contentLower = row.content.toLowerCase();
|
|
60
|
+
// Bug Fix #9: denominator is ftsTokens.length, not raw query word count
|
|
61
|
+
const matchedCount = ftsTokens.filter(w => contentLower.includes(w)).length;
|
|
62
|
+
const wordMatchRatio = ftsTokens.length > 0 ? matchedCount / ftsTokens.length : 0;
|
|
63
|
+
const score = 0.5 + wordMatchRatio * 0.5;
|
|
64
|
+
results.push({
|
|
65
|
+
id: row.id,
|
|
66
|
+
content: row.content,
|
|
67
|
+
category: row.category || 'general',
|
|
68
|
+
confidence: row.confidence || 0.7,
|
|
69
|
+
timestamp: row.timestamp,
|
|
70
|
+
entities: JSON.parse(row.entities_json || '[]'),
|
|
71
|
+
score,
|
|
72
|
+
source: 'direct',
|
|
73
|
+
source_conversation_id: row.source_conversation_id,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.warn('[brain-core/fact-retrieval] FTS search failed', { err: String(err) });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Semantic search (no-op until Day 4 vectors)
|
|
82
|
+
try {
|
|
83
|
+
const semanticResults = await semanticSearch(t, query, { limit: limit * 2, type: 'note' });
|
|
84
|
+
for (const sr of semanticResults) {
|
|
85
|
+
if (!sr.metadata.source_path.startsWith('fact://'))
|
|
86
|
+
continue;
|
|
87
|
+
const semanticScore = 1 - sr.distance;
|
|
88
|
+
let merged = false;
|
|
89
|
+
for (const existing of results) {
|
|
90
|
+
if (wordOverlap(existing.content, sr.content) > 0.8) {
|
|
91
|
+
existing.score = Math.max(existing.score, semanticScore);
|
|
92
|
+
merged = true;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!merged) {
|
|
97
|
+
results.push({
|
|
98
|
+
id: 0,
|
|
99
|
+
content: sr.content,
|
|
100
|
+
category: 'general',
|
|
101
|
+
confidence: 0.7,
|
|
102
|
+
timestamp: sr.metadata.timestamp ?? new Date().toISOString(),
|
|
103
|
+
entities: [],
|
|
104
|
+
score: semanticScore,
|
|
105
|
+
source: 'direct',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch { /* semantic search is best-effort */ }
|
|
111
|
+
// Deduplicate by content overlap
|
|
112
|
+
const deduped = [];
|
|
113
|
+
for (const fact of results) {
|
|
114
|
+
let isDuplicate = false;
|
|
115
|
+
for (const existing of deduped) {
|
|
116
|
+
if (wordOverlap(existing.content, fact.content) > 0.8) {
|
|
117
|
+
if (fact.score > existing.score)
|
|
118
|
+
Object.assign(existing, fact);
|
|
119
|
+
isDuplicate = true;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!isDuplicate)
|
|
124
|
+
deduped.push(fact);
|
|
125
|
+
}
|
|
126
|
+
return deduped.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
127
|
+
}
|
|
128
|
+
// ─── Layer 2: Entity expansion ────────────────────────────────────────────────
|
|
129
|
+
const HOP_DISTANCE_PENALTY = { 0: 1.0, 1: 0.7, 2: 0.5, 3: 0.3 };
|
|
130
|
+
function traverseEntityGraph(entityDb, seedIds, maxHops, maxEntities) {
|
|
131
|
+
const visited = new Map();
|
|
132
|
+
for (const id of seedIds)
|
|
133
|
+
visited.set(id, 0);
|
|
134
|
+
let frontier = [...seedIds];
|
|
135
|
+
for (let hop = 0; hop < maxHops && frontier.length > 0; hop++) {
|
|
136
|
+
const next = [];
|
|
137
|
+
for (const eid of frontier) {
|
|
138
|
+
try {
|
|
139
|
+
const connected = entityDb.prepare(`
|
|
140
|
+
SELECT CASE WHEN source_id = ? THEN target_id ELSE source_id END as cid
|
|
141
|
+
FROM entity_relations
|
|
142
|
+
WHERE source_id = ? OR target_id = ?
|
|
143
|
+
ORDER BY strength DESC LIMIT 10
|
|
144
|
+
`).all(eid, eid, eid);
|
|
145
|
+
for (const c of connected) {
|
|
146
|
+
if (!visited.has(c.cid) && visited.size < maxEntities) {
|
|
147
|
+
visited.set(c.cid, hop + 1);
|
|
148
|
+
next.push(c.cid);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch { /* skip */ }
|
|
153
|
+
}
|
|
154
|
+
frontier = next;
|
|
155
|
+
}
|
|
156
|
+
return Array.from(visited.entries()).map(([id, hopDistance]) => ({ id, hopDistance }));
|
|
157
|
+
}
|
|
158
|
+
async function expandByEntities(t, query, existingFacts, limit) {
|
|
159
|
+
const expanded = [];
|
|
160
|
+
try {
|
|
161
|
+
const entityDb = getDb(t, 'entityGraph');
|
|
162
|
+
const queryLower = query.toLowerCase();
|
|
163
|
+
const allEntities = entityDb.prepare('SELECT id, name FROM entities ORDER BY mention_count DESC LIMIT 200').all();
|
|
164
|
+
const matched = allEntities.filter(e => e.name.length >= 3 && queryLower.includes(e.name.toLowerCase()));
|
|
165
|
+
if (matched.length === 0)
|
|
166
|
+
return [];
|
|
167
|
+
const seedIds = matched.slice(0, 5).map(e => e.id);
|
|
168
|
+
const reached = traverseEntityGraph(entityDb, seedIds, 1, 10);
|
|
169
|
+
const nameMap = new Map(allEntities.map(e => [e.id, e.name]));
|
|
170
|
+
const existingContent = existingFacts.map(f => f.content);
|
|
171
|
+
for (const r of reached) {
|
|
172
|
+
const name = nameMap.get(r.id);
|
|
173
|
+
if (!name)
|
|
174
|
+
continue;
|
|
175
|
+
const entityFacts = await getFactsForEntity(t, name, { latestOnly: true, limit: 10 });
|
|
176
|
+
const penalty = HOP_DISTANCE_PENALTY[r.hopDistance] ?? 0.3;
|
|
177
|
+
const source = r.hopDistance === 0 ? 'entity_expansion' : 'graph_expansion';
|
|
178
|
+
for (const ef of entityFacts) {
|
|
179
|
+
if (existingContent.some(c => wordOverlap(c, ef.content) > 0.8))
|
|
180
|
+
continue;
|
|
181
|
+
if (expanded.some(ex => wordOverlap(ex.content, ef.content) > 0.8))
|
|
182
|
+
continue;
|
|
183
|
+
if (r.hopDistance > 0 && wordOverlap(queryLower, ef.content.toLowerCase()) < 0.1)
|
|
184
|
+
continue;
|
|
185
|
+
expanded.push({
|
|
186
|
+
id: ef.id,
|
|
187
|
+
content: ef.content,
|
|
188
|
+
category: ef.category || 'general',
|
|
189
|
+
confidence: ef.confidence,
|
|
190
|
+
timestamp: ef.timestamp,
|
|
191
|
+
entities: ef.entities,
|
|
192
|
+
score: (r.hopDistance === 0 ? 1.0 : ef.confidence || 0.7) * penalty,
|
|
193
|
+
source,
|
|
194
|
+
source_conversation_id: ef.sourceConversationId,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
console.warn('[brain-core/fact-retrieval] entity expansion failed', { err: String(err) });
|
|
201
|
+
}
|
|
202
|
+
return expanded.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
203
|
+
}
|
|
204
|
+
async function findSupportingContext(t, facts, maxFacts, maxPerFact) {
|
|
205
|
+
const supporting = [];
|
|
206
|
+
try {
|
|
207
|
+
const db = getDb(t, 'timeline');
|
|
208
|
+
for (const fact of facts.slice(0, maxFacts)) {
|
|
209
|
+
let parentPath = null;
|
|
210
|
+
try {
|
|
211
|
+
const row = db.prepare('SELECT source_conversation_id FROM facts WHERE id = ?').get(fact.id);
|
|
212
|
+
if (row)
|
|
213
|
+
parentPath = row.source_conversation_id;
|
|
214
|
+
}
|
|
215
|
+
catch { /* best-effort */ }
|
|
216
|
+
if (!parentPath)
|
|
217
|
+
continue;
|
|
218
|
+
try {
|
|
219
|
+
const segs = db.prepare(`
|
|
220
|
+
SELECT source_path, summary, timestamp FROM timeline_events
|
|
221
|
+
WHERE source_path LIKE ? OR source_path = ?
|
|
222
|
+
ORDER BY timestamp ASC LIMIT ?
|
|
223
|
+
`).all(`${parentPath}%`, parentPath, maxPerFact);
|
|
224
|
+
for (const seg of segs) {
|
|
225
|
+
if (!seg.summary || seg.summary.trim().length < 10)
|
|
226
|
+
continue;
|
|
227
|
+
supporting.push({
|
|
228
|
+
content: seg.summary,
|
|
229
|
+
source_path: seg.source_path,
|
|
230
|
+
timestamp: seg.timestamp,
|
|
231
|
+
related_fact_id: fact.id,
|
|
232
|
+
score: fact.score,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch { /* best-effort */ }
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
console.warn('[brain-core/fact-retrieval] supporting context failed', { err: String(err) });
|
|
241
|
+
}
|
|
242
|
+
return supporting;
|
|
243
|
+
}
|
|
244
|
+
// ─── Layer 4: Context assembly ────────────────────────────────────────────────
|
|
245
|
+
function assembleContext(facts, supporting, tokenBudget) {
|
|
246
|
+
const lines = [];
|
|
247
|
+
let tokens = 0;
|
|
248
|
+
let pruned = 0;
|
|
249
|
+
lines.push('## Relevant Facts\n');
|
|
250
|
+
tokens += estimateTokens('## Relevant Facts\n');
|
|
251
|
+
for (const fact of facts) {
|
|
252
|
+
const line = `- [${fact.category}] ${fact.content} (confidence: ${Math.round(fact.confidence * 100)}%)\n`;
|
|
253
|
+
const t = estimateTokens(line);
|
|
254
|
+
if (tokens + t > tokenBudget * 0.7) {
|
|
255
|
+
pruned++;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
lines.push(line);
|
|
259
|
+
tokens += t;
|
|
260
|
+
}
|
|
261
|
+
if (supporting.length > 0) {
|
|
262
|
+
lines.push('\n## Supporting Context\n');
|
|
263
|
+
tokens += estimateTokens('\n## Supporting Context\n');
|
|
264
|
+
for (const chunk of supporting) {
|
|
265
|
+
const line = `${chunk.content.slice(0, 300)}\n`;
|
|
266
|
+
const t = estimateTokens(line);
|
|
267
|
+
if (tokens + t > tokenBudget) {
|
|
268
|
+
pruned++;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
lines.push(line);
|
|
272
|
+
tokens += t;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return { assembled: lines.join(''), tokenEstimate: tokens, pruned };
|
|
276
|
+
}
|
|
277
|
+
// ─── Main entry point ─────────────────────────────────────────────────────────
|
|
278
|
+
export async function factFirstSearch(t, query, options = {}) {
|
|
279
|
+
const { limit = 15, tokenBudget = 4000, includeSupporting = true, maxSupportingPerFact = 2, } = options;
|
|
280
|
+
// Layer 1
|
|
281
|
+
const directFacts = await searchFactsDirect(t, query, limit * 2);
|
|
282
|
+
// Layer 2
|
|
283
|
+
const expandedFacts = await expandByEntities(t, query, directFacts, limit);
|
|
284
|
+
const allFacts = [...expandedFacts, ...directFacts]
|
|
285
|
+
.sort((a, b) => b.score - a.score);
|
|
286
|
+
// Layer 2.5: scene expansion + bridge discovery
|
|
287
|
+
let sceneExpandedCount = 0;
|
|
288
|
+
let bridgeCount = 0;
|
|
289
|
+
const seenIds = new Set(allFacts.map(f => f.id));
|
|
290
|
+
try {
|
|
291
|
+
const db = getDb(t, 'timeline');
|
|
292
|
+
for (const topFact of allFacts.slice(0, 5)) {
|
|
293
|
+
let convId = topFact.source_conversation_id;
|
|
294
|
+
if (!convId && topFact.id > 0) {
|
|
295
|
+
try {
|
|
296
|
+
const row = db.prepare('SELECT source_conversation_id FROM facts WHERE id = ?')
|
|
297
|
+
.get(topFact.id);
|
|
298
|
+
if (row)
|
|
299
|
+
convId = row.source_conversation_id;
|
|
300
|
+
}
|
|
301
|
+
catch { /* best-effort */ }
|
|
302
|
+
}
|
|
303
|
+
if (!convId)
|
|
304
|
+
continue;
|
|
305
|
+
try {
|
|
306
|
+
const nearby = db.prepare(`
|
|
307
|
+
SELECT id, content, category, confidence, timestamp, entities_json, source_conversation_id
|
|
308
|
+
FROM facts
|
|
309
|
+
WHERE source_conversation_id = ? AND id != ?
|
|
310
|
+
AND COALESCE(is_latest, 1) = 1
|
|
311
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
312
|
+
ORDER BY ABS(id - ?) ASC LIMIT 3
|
|
313
|
+
`).all(convId, topFact.id, topFact.id);
|
|
314
|
+
for (const n of nearby) {
|
|
315
|
+
if (!seenIds.has(n.id)) {
|
|
316
|
+
seenIds.add(n.id);
|
|
317
|
+
sceneExpandedCount++;
|
|
318
|
+
allFacts.push({
|
|
319
|
+
id: n.id, content: n.content, category: n.category || 'general',
|
|
320
|
+
confidence: n.confidence || 0.7, timestamp: n.timestamp,
|
|
321
|
+
entities: JSON.parse(n.entities_json || '[]'),
|
|
322
|
+
score: topFact.score * 0.6, source: 'scene_expansion',
|
|
323
|
+
source_conversation_id: n.source_conversation_id,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch { /* best-effort */ }
|
|
329
|
+
}
|
|
330
|
+
// Bridge: find facts that share entities with multiple top results
|
|
331
|
+
const topFacts = allFacts.slice(0, 3);
|
|
332
|
+
if (topFacts.length >= 2) {
|
|
333
|
+
const entitySets = topFacts.map(f => new Set(f.entities.map(e => e.toLowerCase())));
|
|
334
|
+
try {
|
|
335
|
+
const bridgeCandidates = db.prepare(`
|
|
336
|
+
SELECT id, content, category, confidence, timestamp, entities_json
|
|
337
|
+
FROM facts
|
|
338
|
+
WHERE COALESCE(is_latest, 1) = 1
|
|
339
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
340
|
+
LIMIT 100
|
|
341
|
+
`).all();
|
|
342
|
+
for (const candidate of bridgeCandidates) {
|
|
343
|
+
if (seenIds.has(candidate.id))
|
|
344
|
+
continue;
|
|
345
|
+
const candidateEntities = new Set(JSON.parse(candidate.entities_json || '[]').map(e => e.toLowerCase()));
|
|
346
|
+
let setsConnected = 0;
|
|
347
|
+
for (const es of entitySets) {
|
|
348
|
+
if ([...candidateEntities].some(e => es.has(e)))
|
|
349
|
+
setsConnected++;
|
|
350
|
+
}
|
|
351
|
+
if (setsConnected >= 2) {
|
|
352
|
+
seenIds.add(candidate.id);
|
|
353
|
+
bridgeCount++;
|
|
354
|
+
allFacts.push({
|
|
355
|
+
id: candidate.id, content: candidate.content,
|
|
356
|
+
category: candidate.category || 'general',
|
|
357
|
+
confidence: candidate.confidence || 0.7, timestamp: candidate.timestamp,
|
|
358
|
+
entities: JSON.parse(candidate.entities_json || '[]'),
|
|
359
|
+
score: 0.4, source: 'bridge',
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch { /* best-effort */ }
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
console.warn('[brain-core/fact-retrieval] scene/bridge expansion failed', { err: String(err) });
|
|
369
|
+
}
|
|
370
|
+
// Layer 3: supporting context
|
|
371
|
+
const supporting = includeSupporting
|
|
372
|
+
? await findSupportingContext(t, allFacts.slice(0, limit), Math.min(limit, 10), maxSupportingPerFact)
|
|
373
|
+
: [];
|
|
374
|
+
// Layer 4: assemble context
|
|
375
|
+
const topFacts = allFacts.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
376
|
+
const { assembled, tokenEstimate, pruned } = assembleContext(topFacts, supporting, tokenBudget);
|
|
377
|
+
const directCount = topFacts.filter(f => f.source === 'direct').length;
|
|
378
|
+
const expandedCount = topFacts.filter(f => f.source === 'entity_expansion').length;
|
|
379
|
+
const graphCount = topFacts.filter(f => f.source === 'graph_expansion').length;
|
|
380
|
+
return {
|
|
381
|
+
facts: topFacts,
|
|
382
|
+
supporting_context: supporting.map(s => ({
|
|
383
|
+
content: s.content,
|
|
384
|
+
source_path: s.source_path,
|
|
385
|
+
timestamp: s.timestamp,
|
|
386
|
+
related_fact_id: s.related_fact_id,
|
|
387
|
+
})),
|
|
388
|
+
assembled_context: assembled,
|
|
389
|
+
token_estimate: tokenEstimate,
|
|
390
|
+
stats: {
|
|
391
|
+
direct_facts: directCount,
|
|
392
|
+
expanded_facts: expandedCount,
|
|
393
|
+
graph_expanded_facts: graphCount,
|
|
394
|
+
scene_expanded_facts: sceneExpandedCount,
|
|
395
|
+
bridge_facts: bridgeCount,
|
|
396
|
+
supporting_chunks: supporting.length,
|
|
397
|
+
pruned_items: pruned,
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=fact-retrieval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-retrieval.js","sourceRoot":"","sources":["../src/fact-retrieval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { TenantContext, FactCategory, Fact } from '@kybernesis/brain-contracts';
|
|
2
|
+
export declare const VALID_CATEGORIES: Set<"biographical" | "preference" | "event" | "relationship" | "temporal" | "opinion" | "plan" | "general">;
|
|
3
|
+
export declare function ensureFactsTable(t: TenantContext): Promise<void>;
|
|
4
|
+
export declare function storeFact(t: TenantContext, fact: Omit<Fact, 'id' | 'createdAt' | 'isLatest' | 'accessCount' | 'isRetracted'>): Promise<number>;
|
|
5
|
+
export declare function retractFact(t: TenantContext, factId: number, retractedBy?: string): Promise<void>;
|
|
6
|
+
export declare function reinforceFact(t: TenantContext, factId: number): Promise<void>;
|
|
7
|
+
export declare function getFactById(t: TenantContext, factId: number): Promise<Fact | null>;
|
|
8
|
+
export declare function getFactsForEntity(t: TenantContext, entity: string, options?: {
|
|
9
|
+
latestOnly?: boolean;
|
|
10
|
+
limit?: number;
|
|
11
|
+
category?: FactCategory;
|
|
12
|
+
}): Promise<Fact[]>;
|
|
13
|
+
export declare function markFactSuperseded(t: TenantContext, oldFactId: number, newFactId: number): Promise<void>;
|
|
14
|
+
export declare function factsCount(t: TenantContext): Promise<number>;
|
|
15
|
+
export declare function listFacts(t: TenantContext, options?: {
|
|
16
|
+
limit?: number;
|
|
17
|
+
offset?: number;
|
|
18
|
+
latestOnly?: boolean;
|
|
19
|
+
category?: FactCategory;
|
|
20
|
+
}): Promise<Fact[]>;
|
|
21
|
+
export declare function listTemporalFacts(t: TenantContext, options?: {
|
|
22
|
+
includeExpired?: boolean;
|
|
23
|
+
limit?: number;
|
|
24
|
+
}): Promise<Fact[]>;
|
|
25
|
+
export declare function searchFactsFts(t: TenantContext, query: string, limit?: number): Promise<Fact[]>;
|
|
26
|
+
//# sourceMappingURL=fact-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-store.d.ts","sourceRoot":"","sources":["../src/fact-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAGrF,eAAO,MAAM,gBAAgB,6GAG3B,CAAC;AAgGH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,SAAS,CAC7B,CAAC,EAAE,aAAa,EAChB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC,GAChF,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,wBAAsB,WAAW,CAC/B,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,MAA0B,GACtC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,aAAa,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAInF;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAKxF;AAED,wBAAsB,iBAAiB,CACrC,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAO,GAC9E,OAAO,CAAC,IAAI,EAAE,CAAC,CAqBjB;AAED,wBAAsB,kBAAkB,CACtC,CAAC,EAAE,aAAa,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAKlE;AAED,wBAAsB,SAAS,CAC7B,CAAC,EAAE,aAAa,EAChB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAO,GAC/F,OAAO,CAAC,IAAI,EAAE,CAAC,CAcjB;AAED,wBAAsB,iBAAiB,CACrC,CAAC,EAAE,aAAa,EAChB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,OAAO,CAAC,IAAI,EAAE,CAAC,CAYjB;AAED,wBAAsB,cAAc,CAClC,CAAC,EAAE,aAAa,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,IAAI,EAAE,CAAC,CAgBjB"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { getDb } from '@kybernesis/brain-storage-sqlite';
|
|
2
|
+
import { sanitizeFtsQuery } from './fts-sanitizer.js';
|
|
3
|
+
export const VALID_CATEGORIES = new Set([
|
|
4
|
+
'biographical', 'preference', 'event', 'relationship',
|
|
5
|
+
'temporal', 'opinion', 'plan', 'general',
|
|
6
|
+
]);
|
|
7
|
+
function rowToFact(row) {
|
|
8
|
+
return {
|
|
9
|
+
id: row.id,
|
|
10
|
+
content: row.content,
|
|
11
|
+
sourcePath: row.source_path,
|
|
12
|
+
sourceConversationId: row.source_conversation_id,
|
|
13
|
+
entities: JSON.parse(row.entities_json || '[]'),
|
|
14
|
+
timestamp: row.timestamp,
|
|
15
|
+
confidence: row.confidence,
|
|
16
|
+
category: row.category,
|
|
17
|
+
createdAt: row.created_at,
|
|
18
|
+
isLatest: (row.is_latest ?? 1) === 1,
|
|
19
|
+
supersededBy: row.superseded_by ?? undefined,
|
|
20
|
+
expiresAt: row.expires_at ?? undefined,
|
|
21
|
+
updatedAt: row.updated_at ?? undefined,
|
|
22
|
+
accessCount: row.access_count ?? 0,
|
|
23
|
+
sourceType: row.source_type ?? 'chat',
|
|
24
|
+
isRetracted: (row.is_retracted ?? 0) === 1,
|
|
25
|
+
retractedBy: row.retracted_by ?? undefined,
|
|
26
|
+
lastReinforcedAt: row.last_reinforced_at ?? undefined,
|
|
27
|
+
projectId: row.project_id ?? undefined,
|
|
28
|
+
tags: JSON.parse(row.tags_json || '[]'),
|
|
29
|
+
classification: row.classification ?? undefined,
|
|
30
|
+
connectionId: row.connection_id ?? undefined,
|
|
31
|
+
sourceDid: row.source_did ?? undefined,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// ─── Schema initialization ────────────────────────────────────────────────────
|
|
35
|
+
// Facts table lives in timeline.db (same file as timeline_events).
|
|
36
|
+
// Schema is created by timeline.ts ensureSchema. This module only ensures
|
|
37
|
+
// the FTS index and triggers exist.
|
|
38
|
+
const initialized = new Set();
|
|
39
|
+
function ensureFactsFts(t) {
|
|
40
|
+
if (initialized.has(t.slug))
|
|
41
|
+
return;
|
|
42
|
+
const db = getDb(t, 'timeline');
|
|
43
|
+
// Bug Fix 1 (CANONICAL.md §6): The non-contentless facts_fts table must use
|
|
44
|
+
// explicit DELETE FROM ... WHERE rowid = ? in triggers, NOT the ('delete', ...)
|
|
45
|
+
// command form which is only valid for contentless FTS5 tables. Using the wrong
|
|
46
|
+
// form threw SqliteError on every UPDATE/DELETE, silently swallowed by empty
|
|
47
|
+
// catch{} in decay.ts, meaning KAD has NEVER expired temporal facts in production.
|
|
48
|
+
db.exec(`
|
|
49
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS facts_fts USING fts5(content, entities);
|
|
50
|
+
|
|
51
|
+
CREATE TRIGGER IF NOT EXISTS facts_fts_ai AFTER INSERT ON facts BEGIN
|
|
52
|
+
INSERT INTO facts_fts(rowid, content, entities) VALUES (new.id, new.content, new.entities_json);
|
|
53
|
+
END;
|
|
54
|
+
|
|
55
|
+
CREATE TRIGGER IF NOT EXISTS facts_fts_ad AFTER DELETE ON facts BEGIN
|
|
56
|
+
DELETE FROM facts_fts WHERE rowid = old.id;
|
|
57
|
+
END;
|
|
58
|
+
|
|
59
|
+
CREATE TRIGGER IF NOT EXISTS facts_fts_au AFTER UPDATE ON facts BEGIN
|
|
60
|
+
DELETE FROM facts_fts WHERE rowid = old.id;
|
|
61
|
+
INSERT INTO facts_fts(rowid, content, entities) VALUES (new.id, new.content, new.entities_json);
|
|
62
|
+
END;
|
|
63
|
+
`);
|
|
64
|
+
initialized.add(t.slug);
|
|
65
|
+
}
|
|
66
|
+
// ─── Operations ───────────────────────────────────────────────────────────────
|
|
67
|
+
export async function ensureFactsTable(t) {
|
|
68
|
+
ensureFactsFts(t);
|
|
69
|
+
}
|
|
70
|
+
export async function storeFact(t, fact) {
|
|
71
|
+
ensureFactsFts(t);
|
|
72
|
+
const db = getDb(t, 'timeline');
|
|
73
|
+
const result = db.prepare(`
|
|
74
|
+
INSERT OR REPLACE INTO facts
|
|
75
|
+
(content, source_path, source_conversation_id, entities_json, timestamp, confidence, category,
|
|
76
|
+
expires_at, source_type, project_id, tags_json, classification, connection_id, source_did)
|
|
77
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
78
|
+
`).run(fact.content, fact.sourcePath, fact.sourceConversationId, JSON.stringify(fact.entities), fact.timestamp, fact.confidence, fact.category, fact.expiresAt ?? null, fact.sourceType ?? 'chat', fact.projectId ?? null, JSON.stringify(fact.tags ?? []), fact.classification ?? null, fact.connectionId ?? null, fact.sourceDid ?? null);
|
|
79
|
+
return result.lastInsertRowid;
|
|
80
|
+
}
|
|
81
|
+
export async function retractFact(t, factId, retractedBy = 'user-correction') {
|
|
82
|
+
ensureFactsFts(t);
|
|
83
|
+
const db = getDb(t, 'timeline');
|
|
84
|
+
db.prepare(`
|
|
85
|
+
UPDATE facts SET is_retracted = 1, retracted_by = ?, is_latest = 0, updated_at = datetime('now')
|
|
86
|
+
WHERE id = ?
|
|
87
|
+
`).run(retractedBy, factId);
|
|
88
|
+
}
|
|
89
|
+
export async function reinforceFact(t, factId) {
|
|
90
|
+
ensureFactsFts(t);
|
|
91
|
+
const db = getDb(t, 'timeline');
|
|
92
|
+
db.prepare(`UPDATE facts SET last_reinforced_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`).run(factId);
|
|
93
|
+
}
|
|
94
|
+
export async function getFactById(t, factId) {
|
|
95
|
+
ensureFactsFts(t);
|
|
96
|
+
const db = getDb(t, 'timeline');
|
|
97
|
+
const row = db.prepare('SELECT * FROM facts WHERE id = ?').get(factId);
|
|
98
|
+
return row ? rowToFact(row) : null;
|
|
99
|
+
}
|
|
100
|
+
export async function getFactsForEntity(t, entity, options = {}) {
|
|
101
|
+
const { latestOnly = true, limit = 20, category } = options;
|
|
102
|
+
ensureFactsFts(t);
|
|
103
|
+
const db = getDb(t, 'timeline');
|
|
104
|
+
const escapedEntity = entity.toLowerCase().replace(/[%_\\]/g, ch => `\\${ch}`);
|
|
105
|
+
const entityPattern = `%${escapedEntity}%`;
|
|
106
|
+
let sql = `
|
|
107
|
+
SELECT * FROM facts
|
|
108
|
+
WHERE LOWER(entities_json) LIKE ? ESCAPE '\\'
|
|
109
|
+
AND COALESCE(is_retracted, 0) = 0
|
|
110
|
+
`;
|
|
111
|
+
const params = [entityPattern];
|
|
112
|
+
if (latestOnly) {
|
|
113
|
+
sql += ` AND COALESCE(is_latest, 1) = 1`;
|
|
114
|
+
}
|
|
115
|
+
if (category) {
|
|
116
|
+
sql += ` AND category = ?`;
|
|
117
|
+
params.push(category);
|
|
118
|
+
}
|
|
119
|
+
sql += ` ORDER BY timestamp DESC LIMIT ?`;
|
|
120
|
+
params.push(limit);
|
|
121
|
+
return db.prepare(sql).all(...params).map(rowToFact);
|
|
122
|
+
}
|
|
123
|
+
export async function markFactSuperseded(t, oldFactId, newFactId) {
|
|
124
|
+
ensureFactsFts(t);
|
|
125
|
+
const db = getDb(t, 'timeline');
|
|
126
|
+
db.prepare('UPDATE facts SET is_latest = 0, superseded_by = ? WHERE id = ?').run(newFactId, oldFactId);
|
|
127
|
+
}
|
|
128
|
+
export async function factsCount(t) {
|
|
129
|
+
ensureFactsFts(t);
|
|
130
|
+
const db = getDb(t, 'timeline');
|
|
131
|
+
const { count } = db.prepare('SELECT COUNT(*) as count FROM facts WHERE COALESCE(is_retracted, 0) = 0').get();
|
|
132
|
+
return count;
|
|
133
|
+
}
|
|
134
|
+
export async function listFacts(t, options = {}) {
|
|
135
|
+
const { limit = 50, offset = 0, latestOnly = true, category } = options;
|
|
136
|
+
ensureFactsFts(t);
|
|
137
|
+
const db = getDb(t, 'timeline');
|
|
138
|
+
let sql = 'SELECT * FROM facts WHERE COALESCE(is_retracted, 0) = 0';
|
|
139
|
+
const params = [];
|
|
140
|
+
if (latestOnly) {
|
|
141
|
+
sql += ' AND COALESCE(is_latest, 1) = 1';
|
|
142
|
+
}
|
|
143
|
+
if (category) {
|
|
144
|
+
sql += ' AND category = ?';
|
|
145
|
+
params.push(category);
|
|
146
|
+
}
|
|
147
|
+
sql += ' ORDER BY timestamp DESC LIMIT ? OFFSET ?';
|
|
148
|
+
params.push(limit, offset);
|
|
149
|
+
return db.prepare(sql).all(...params).map(rowToFact);
|
|
150
|
+
}
|
|
151
|
+
export async function listTemporalFacts(t, options = {}) {
|
|
152
|
+
const { includeExpired = false, limit = 50 } = options;
|
|
153
|
+
ensureFactsFts(t);
|
|
154
|
+
const db = getDb(t, 'timeline');
|
|
155
|
+
let sql = `SELECT * FROM facts WHERE expires_at IS NOT NULL AND COALESCE(is_retracted, 0) = 0`;
|
|
156
|
+
const params = [];
|
|
157
|
+
if (!includeExpired) {
|
|
158
|
+
sql += ` AND (expires_at IS NULL OR expires_at > datetime('now'))`;
|
|
159
|
+
}
|
|
160
|
+
sql += ' ORDER BY expires_at ASC LIMIT ?';
|
|
161
|
+
params.push(limit);
|
|
162
|
+
return db.prepare(sql).all(...params).map(rowToFact);
|
|
163
|
+
}
|
|
164
|
+
export async function searchFactsFts(t, query, limit = 20) {
|
|
165
|
+
ensureFactsFts(t);
|
|
166
|
+
const db = getDb(t, 'timeline');
|
|
167
|
+
const sanitized = sanitizeFtsQuery(query);
|
|
168
|
+
if (!sanitized)
|
|
169
|
+
return [];
|
|
170
|
+
try {
|
|
171
|
+
const rowids = db.prepare(`SELECT rowid FROM facts_fts WHERE facts_fts MATCH ? LIMIT ?`).all(sanitized, limit);
|
|
172
|
+
if (rowids.length === 0)
|
|
173
|
+
return [];
|
|
174
|
+
const placeholders = rowids.map(() => '?').join(',');
|
|
175
|
+
return db.prepare(`SELECT * FROM facts WHERE id IN (${placeholders})`).all(...rowids.map(r => r.rowid)).map(rowToFact);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=fact-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-store.js","sourceRoot":"","sources":["../src/fact-store.ts"],"names":[],"mappings":"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"}
|