@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,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning step — port of KAD's sleep/steps/reasoning.ts.
|
|
3
|
+
*
|
|
4
|
+
* Two LLM passes per entity (only entities with ≥3 facts):
|
|
5
|
+
* 1. Deduction (confidence 0.80-0.95) — logically certain conclusions
|
|
6
|
+
* 2. Induction (confidence 0.60-0.75) — probable patterns from ≥3 data points
|
|
7
|
+
*
|
|
8
|
+
* Marks existing insights stale before generating new ones; saves new
|
|
9
|
+
* insights tagged 'inference' (deduction) or 'pattern' (induction).
|
|
10
|
+
*/
|
|
11
|
+
import { getDb } from '@kybernesis/brain-storage-sqlite';
|
|
12
|
+
import { callClaude } from '../../claude-call.js';
|
|
13
|
+
import { getEntitiesForReasoning, markEntityReasoned, saveEntityInsight, markInsightsStale, getTypedRelationships, } from '../../entity-graph.js';
|
|
14
|
+
import { getFactsForEntity } from '../../fact-store.js';
|
|
15
|
+
const DEDUCTION_PROMPT = `Given these facts about "{name}" and connected entities, what can you LOGICALLY DERIVE that is CERTAINLY TRUE?
|
|
16
|
+
|
|
17
|
+
Every conclusion must follow from 2+ existing facts. Only include things that are definitely true based on the evidence — no speculation.
|
|
18
|
+
|
|
19
|
+
Facts about {name}:
|
|
20
|
+
{facts}
|
|
21
|
+
|
|
22
|
+
{connectedSection}
|
|
23
|
+
|
|
24
|
+
Return a JSON array of insights. Each must have "insight" (the conclusion), "reasoning" (which facts support it), and "confidence" (0.80-0.95).
|
|
25
|
+
Return [] if nothing can be logically derived.
|
|
26
|
+
|
|
27
|
+
Example: [{"insight":"David leads a Darkstar portfolio company","reasoning":"David is CEO of Ohana + Ohana is a Darkstar portfolio company","confidence":0.85}]`;
|
|
28
|
+
const INDUCTION_PROMPT = `Given these observations about "{name}", what PATTERNS do you detect? What is PROBABLY true?
|
|
29
|
+
|
|
30
|
+
Require 3+ data points to propose a pattern. These are probable, not certain.
|
|
31
|
+
|
|
32
|
+
Facts about {name}:
|
|
33
|
+
{facts}
|
|
34
|
+
|
|
35
|
+
Mention patterns:
|
|
36
|
+
- Total mentions: {mentionCount}
|
|
37
|
+
- First seen: {firstSeen}
|
|
38
|
+
- Last seen: {lastSeen}
|
|
39
|
+
{coOccurrences}
|
|
40
|
+
|
|
41
|
+
Return a JSON array of pattern insights. Each must have "insight" (the pattern), "reasoning" (the evidence), and "confidence" (0.60-0.75).
|
|
42
|
+
Return [] if no clear patterns.
|
|
43
|
+
|
|
44
|
+
Example: [{"insight":"Nick is a regular in the AI meetup circuit","reasoning":"Appears at 6 different AI events over 3 months","confidence":0.70}]`;
|
|
45
|
+
function parseInsights(response) {
|
|
46
|
+
const jsonMatch = (response ?? '').match(/\[[\s\S]*\]/);
|
|
47
|
+
if (!jsonMatch)
|
|
48
|
+
return [];
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
51
|
+
if (!Array.isArray(parsed))
|
|
52
|
+
return [];
|
|
53
|
+
return parsed.filter((item) => {
|
|
54
|
+
if (!item || typeof item !== 'object')
|
|
55
|
+
return false;
|
|
56
|
+
return (typeof item.insight === 'string' &&
|
|
57
|
+
item.insight.length > 5 &&
|
|
58
|
+
typeof item.reasoning === 'string' &&
|
|
59
|
+
typeof item.confidence === 'number');
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function runReasoningStep(t, config) {
|
|
67
|
+
if (!config.enableReasoning)
|
|
68
|
+
return { count: 0, processed: 0 };
|
|
69
|
+
const maxPerRun = config.maxReasoningPerRun || 5;
|
|
70
|
+
let insightsCreated = 0;
|
|
71
|
+
let processed = 0;
|
|
72
|
+
const errors = [];
|
|
73
|
+
try {
|
|
74
|
+
const entities = await getEntitiesForReasoning(t, maxPerRun);
|
|
75
|
+
if (entities.length === 0)
|
|
76
|
+
return { count: 0, processed: 0 };
|
|
77
|
+
const db = getDb(t, 'entityGraph');
|
|
78
|
+
for (const entity of entities) {
|
|
79
|
+
processed++;
|
|
80
|
+
try {
|
|
81
|
+
const facts = await getFactsForEntity(t, entity.name, { latestOnly: true, limit: 20 });
|
|
82
|
+
if (facts.length < 3) {
|
|
83
|
+
await markEntityReasoned(t, entity.id);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const factList = facts.map(f => `- ${f.content} (${f.category}, confidence: ${f.confidence})`).join('\n');
|
|
87
|
+
let connectedSection = '';
|
|
88
|
+
try {
|
|
89
|
+
const typedRels = await getTypedRelationships(t, entity.id);
|
|
90
|
+
if (typedRels.length > 0) {
|
|
91
|
+
const connectedParts = [];
|
|
92
|
+
for (const rel of typedRels.slice(0, 5)) {
|
|
93
|
+
const relFacts = await getFactsForEntity(t, rel.entity.name, { latestOnly: true, limit: 5 });
|
|
94
|
+
if (relFacts.length > 0) {
|
|
95
|
+
const relFactList = relFacts.map(f => ` - ${f.content}`).join('\n');
|
|
96
|
+
connectedParts.push(`${rel.entity.name} (${rel.relationship}):\n${relFactList}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (connectedParts.length > 0) {
|
|
100
|
+
connectedSection = `Connected entities:\n${connectedParts.join('\n\n')}`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch { /* non-fatal */ }
|
|
105
|
+
await markInsightsStale(t, entity.id);
|
|
106
|
+
// Pass 1: Deduction
|
|
107
|
+
try {
|
|
108
|
+
const deductionPrompt = DEDUCTION_PROMPT
|
|
109
|
+
.replace(/\{name\}/g, entity.name)
|
|
110
|
+
.replace('{facts}', factList)
|
|
111
|
+
.replace('{connectedSection}', connectedSection || 'No connected entities with known facts.');
|
|
112
|
+
const response = await callClaude(deductionPrompt, { model: 'haiku', maxTokens: 512 });
|
|
113
|
+
const deductions = parseInsights(response ?? '');
|
|
114
|
+
for (const d of deductions) {
|
|
115
|
+
const confidence = Math.max(0.80, Math.min(0.95, d.confidence));
|
|
116
|
+
await saveEntityInsight(t, entity.id, 'inference', d.insight, d.reasoning, confidence);
|
|
117
|
+
insightsCreated++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
errors.push(`deduction ${entity.name}: ${String(err)}`);
|
|
122
|
+
}
|
|
123
|
+
// Pass 2: Induction
|
|
124
|
+
try {
|
|
125
|
+
const entityRow = db.prepare('SELECT * FROM entities WHERE id = ?').get(entity.id);
|
|
126
|
+
let coOccurrences = '';
|
|
127
|
+
try {
|
|
128
|
+
const coOccurring = db.prepare(`
|
|
129
|
+
SELECT e2.name, er.strength FROM entity_relations er
|
|
130
|
+
JOIN entities e2 ON e2.id = CASE WHEN er.source_id = ? THEN er.target_id ELSE er.source_id END
|
|
131
|
+
WHERE (er.source_id = ? OR er.target_id = ?) AND er.strength > 1
|
|
132
|
+
ORDER BY er.strength DESC LIMIT 10
|
|
133
|
+
`).all(entity.id, entity.id, entity.id);
|
|
134
|
+
if (coOccurring.length > 0) {
|
|
135
|
+
coOccurrences = 'Co-occurs with: ' + coOccurring.map(c => `${c.name} (${c.strength}x)`).join(', ');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch { /* non-fatal */ }
|
|
139
|
+
const inductionPrompt = INDUCTION_PROMPT
|
|
140
|
+
.replace(/\{name\}/g, entity.name)
|
|
141
|
+
.replace('{facts}', factList)
|
|
142
|
+
.replace('{mentionCount}', String(entityRow?.mention_count ?? 0))
|
|
143
|
+
.replace('{firstSeen}', entityRow?.first_seen ?? 'unknown')
|
|
144
|
+
.replace('{lastSeen}', entityRow?.last_seen ?? 'unknown')
|
|
145
|
+
.replace('{coOccurrences}', coOccurrences || 'No significant co-occurrences.');
|
|
146
|
+
const response = await callClaude(inductionPrompt, { model: 'haiku', maxTokens: 512 });
|
|
147
|
+
const inductions = parseInsights(response ?? '');
|
|
148
|
+
for (const ind of inductions) {
|
|
149
|
+
const confidence = Math.max(0.60, Math.min(0.75, ind.confidence));
|
|
150
|
+
await saveEntityInsight(t, entity.id, 'pattern', ind.insight, ind.reasoning, confidence);
|
|
151
|
+
insightsCreated++;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
errors.push(`induction ${entity.name}: ${String(err)}`);
|
|
156
|
+
}
|
|
157
|
+
await markEntityReasoned(t, entity.id);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
errors.push(`reasoning ${entity.name}: ${String(err)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
errors.push(`reasoning step: ${String(err)}`);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
count: insightsCreated,
|
|
169
|
+
processed,
|
|
170
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=reasoning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning.js","sourceRoot":"","sources":["../../../src/sleep/steps/reasoning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarize step — port of KAD's sleep/steps/summarize.ts.
|
|
3
|
+
*
|
|
4
|
+
* Two phases:
|
|
5
|
+
* 1. Tier-changed items from maintenance_queue (task=resummarize)
|
|
6
|
+
* 2. Items with missing/short/raw-content/over-long summaries, skipping
|
|
7
|
+
* anything enriched in the last 3 days
|
|
8
|
+
*
|
|
9
|
+
* Tier-appropriate prompts: rich for hot (3-5 sentences), compressed for
|
|
10
|
+
* archive (1-2), normal for warm. Output is post-processed to strip common
|
|
11
|
+
* LLM preambles.
|
|
12
|
+
*/
|
|
13
|
+
import type { TenantContext } from '@kybernesis/brain-contracts';
|
|
14
|
+
import type { SleepConfig } from '../config.js';
|
|
15
|
+
export interface SummarizeResult {
|
|
16
|
+
count: number;
|
|
17
|
+
durationMs?: number;
|
|
18
|
+
errors?: string[];
|
|
19
|
+
}
|
|
20
|
+
export declare function runSummarizeStep(t: TenantContext, config: SleepConfig): Promise<SummarizeResult>;
|
|
21
|
+
//# sourceMappingURL=summarize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../../../src/sleep/steps/summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAgED,wBAAsB,gBAAgB,CACpC,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CA+I1B"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarize step — port of KAD's sleep/steps/summarize.ts.
|
|
3
|
+
*
|
|
4
|
+
* Two phases:
|
|
5
|
+
* 1. Tier-changed items from maintenance_queue (task=resummarize)
|
|
6
|
+
* 2. Items with missing/short/raw-content/over-long summaries, skipping
|
|
7
|
+
* anything enriched in the last 3 days
|
|
8
|
+
*
|
|
9
|
+
* Tier-appropriate prompts: rich for hot (3-5 sentences), compressed for
|
|
10
|
+
* archive (1-2), normal for warm. Output is post-processed to strip common
|
|
11
|
+
* LLM preambles.
|
|
12
|
+
*/
|
|
13
|
+
import { promises as fs } from 'node:fs';
|
|
14
|
+
import { getDb } from '@kybernesis/brain-storage-sqlite';
|
|
15
|
+
import { callClaude } from '../../claude-call.js';
|
|
16
|
+
import { ensureSleepSchema } from '../db.js';
|
|
17
|
+
function safeParseArray(json) {
|
|
18
|
+
if (!json)
|
|
19
|
+
return [];
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(json);
|
|
22
|
+
if (Array.isArray(parsed))
|
|
23
|
+
return parsed;
|
|
24
|
+
if (typeof parsed === 'string')
|
|
25
|
+
return parsed.split(',').map(s => s.trim()).filter(Boolean);
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function markProcessed(db, queueId) {
|
|
33
|
+
db.prepare(`UPDATE maintenance_queue SET processed_at = datetime('now') WHERE id = ?`).run(queueId);
|
|
34
|
+
}
|
|
35
|
+
function buildSummaryPrompt(content, tier, title, tags, entities, relatedTitles) {
|
|
36
|
+
const context = [];
|
|
37
|
+
if (title)
|
|
38
|
+
context.push(`Title: ${title}`);
|
|
39
|
+
if (tags.length > 0)
|
|
40
|
+
context.push(`Tags: ${tags.join(', ')}`);
|
|
41
|
+
if (entities.length > 0)
|
|
42
|
+
context.push(`People/entities mentioned: ${entities.join(', ')}`);
|
|
43
|
+
if (relatedTitles.length > 0)
|
|
44
|
+
context.push(`Related memories: ${relatedTitles.join(', ')}`);
|
|
45
|
+
const contextBlock = context.length > 0 ? `\nContext:\n${context.join('\n')}\n` : '';
|
|
46
|
+
if (tier === 'hot') {
|
|
47
|
+
return `Summarize this content for a personal knowledge system. This is a HIGH-PRIORITY memory that is frequently accessed. Write a rich, detailed summary (3-5 sentences) that captures:
|
|
48
|
+
- The key topic and what was discussed/decided
|
|
49
|
+
- Who was involved (if anyone mentioned)
|
|
50
|
+
- Any action items, decisions, or insights
|
|
51
|
+
- Why this matters (context/significance)
|
|
52
|
+
|
|
53
|
+
Write in third person, past tense. Be specific and factual, not generic.
|
|
54
|
+
${contextBlock}
|
|
55
|
+
Content:
|
|
56
|
+
${content}`;
|
|
57
|
+
}
|
|
58
|
+
if (tier === 'archive') {
|
|
59
|
+
return `Summarize this content for a personal knowledge system. This is an ARCHIVED memory (low priority, rarely accessed). Write a compressed summary (1-2 sentences) that captures only the core essence — what it was about and one key detail.
|
|
60
|
+
|
|
61
|
+
Write in third person, past tense. Be ultra-concise.
|
|
62
|
+
${contextBlock}
|
|
63
|
+
Content:
|
|
64
|
+
${content}`;
|
|
65
|
+
}
|
|
66
|
+
return `Summarize this content for a personal knowledge system. Write a clear summary (2-3 sentences) that captures:
|
|
67
|
+
- The main topic
|
|
68
|
+
- Key points or decisions
|
|
69
|
+
- Who was involved (if relevant)
|
|
70
|
+
|
|
71
|
+
Write in third person, past tense. Be specific and factual.
|
|
72
|
+
${contextBlock}
|
|
73
|
+
Content:
|
|
74
|
+
${content}`;
|
|
75
|
+
}
|
|
76
|
+
export async function runSummarizeStep(t, config) {
|
|
77
|
+
const timeline = getDb(t, 'timeline');
|
|
78
|
+
const sleep = ensureSleepSchema(t);
|
|
79
|
+
let summarized = 0;
|
|
80
|
+
const errors = [];
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
try {
|
|
83
|
+
const pendingItems = sleep.prepare(`
|
|
84
|
+
SELECT id as queue_id, item_id
|
|
85
|
+
FROM maintenance_queue
|
|
86
|
+
WHERE task = 'resummarize' AND processed_at IS NULL
|
|
87
|
+
ORDER BY priority DESC
|
|
88
|
+
LIMIT ?
|
|
89
|
+
`).all(config.maxSummariesPerRun);
|
|
90
|
+
const remaining = config.maxSummariesPerRun - pendingItems.length;
|
|
91
|
+
const needsSummary = remaining > 0 ? timeline.prepare(`
|
|
92
|
+
SELECT id FROM timeline_events
|
|
93
|
+
WHERE (summary IS NULL
|
|
94
|
+
OR length(summary) < 50
|
|
95
|
+
OR summary LIKE '{%'
|
|
96
|
+
OR summary LIKE '# %'
|
|
97
|
+
OR length(summary) > 500)
|
|
98
|
+
AND (last_enriched IS NULL OR last_enriched < datetime('now', '-3 days'))
|
|
99
|
+
ORDER BY priority DESC
|
|
100
|
+
LIMIT ?
|
|
101
|
+
`).all(remaining) : [];
|
|
102
|
+
const allItemIds = new Set();
|
|
103
|
+
const queueMap = new Map();
|
|
104
|
+
for (const p of pendingItems) {
|
|
105
|
+
allItemIds.add(p.item_id);
|
|
106
|
+
queueMap.set(p.item_id, p.queue_id);
|
|
107
|
+
}
|
|
108
|
+
for (const n of needsSummary) {
|
|
109
|
+
allItemIds.add(n.id.toString());
|
|
110
|
+
}
|
|
111
|
+
if (allItemIds.size === 0)
|
|
112
|
+
return { count: 0 };
|
|
113
|
+
for (const itemId of allItemIds) {
|
|
114
|
+
try {
|
|
115
|
+
const item = timeline.prepare(`
|
|
116
|
+
SELECT id, source_path, title, tier, summary, tags_json, entities_json
|
|
117
|
+
FROM timeline_events WHERE id = ?
|
|
118
|
+
`).get(parseInt(itemId));
|
|
119
|
+
if (!item) {
|
|
120
|
+
if (queueMap.has(itemId))
|
|
121
|
+
markProcessed(sleep, queueMap.get(itemId));
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
let content = '';
|
|
125
|
+
if (item.source_path.startsWith('channel://')) {
|
|
126
|
+
const parts = [];
|
|
127
|
+
if (item.title)
|
|
128
|
+
parts.push(item.title);
|
|
129
|
+
if (item.summary && item.summary.length > 10)
|
|
130
|
+
parts.push(item.summary);
|
|
131
|
+
content = parts.join('\n\n').slice(0, 4000);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
try {
|
|
135
|
+
const raw = await fs.readFile(item.source_path, 'utf-8');
|
|
136
|
+
content = raw.replace(/^---[\s\S]*?---\n*/m, '').slice(0, 4000);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
if (queueMap.has(itemId))
|
|
140
|
+
markProcessed(sleep, queueMap.get(itemId));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (content.length < 20) {
|
|
145
|
+
if (queueMap.has(itemId))
|
|
146
|
+
markProcessed(sleep, queueMap.get(itemId));
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const tags = safeParseArray(item.tags_json);
|
|
150
|
+
const entities = safeParseArray(item.entities_json);
|
|
151
|
+
const edges = sleep.prepare(`
|
|
152
|
+
SELECT
|
|
153
|
+
CASE WHEN from_path = ? THEN to_path ELSE from_path END as related_path,
|
|
154
|
+
shared_tags
|
|
155
|
+
FROM memory_edges
|
|
156
|
+
WHERE from_path = ? OR to_path = ?
|
|
157
|
+
LIMIT 3
|
|
158
|
+
`).all(item.source_path, item.source_path, item.source_path);
|
|
159
|
+
const relatedTitles = [];
|
|
160
|
+
for (const edge of edges) {
|
|
161
|
+
const related = timeline.prepare(`SELECT title FROM timeline_events WHERE source_path = ?`).get(edge.related_path);
|
|
162
|
+
if (related?.title)
|
|
163
|
+
relatedTitles.push(related.title);
|
|
164
|
+
}
|
|
165
|
+
const prompt = buildSummaryPrompt(content, item.tier || 'warm', item.title, tags, entities, relatedTitles);
|
|
166
|
+
const responseText = await callClaude(prompt, { model: 'haiku', maxTokens: 300 });
|
|
167
|
+
const newSummary = (responseText ?? '')
|
|
168
|
+
.replace(/^(Here's|Here is|Summary|Archived Memory Summary|Memory Archive|Summary for Personal Knowledge System)[:\s]*/i, '')
|
|
169
|
+
.replace(/^(the |a )?(ultra-concise|concise|brief|compressed|detailed|rich)?,? ?(detailed )?summary[:\s]*(for (the )?personal knowledge system)?[:\s]*(in third person,? ?(past tense)?[.:\s]*)?/i, '')
|
|
170
|
+
.replace(/^of\s+(?=[A-Z])/m, '')
|
|
171
|
+
.replace(/^for Personal Knowledge System[:\s]*/i, '')
|
|
172
|
+
.trim();
|
|
173
|
+
if (newSummary && newSummary.length > 20) {
|
|
174
|
+
timeline.prepare(`
|
|
175
|
+
UPDATE timeline_events
|
|
176
|
+
SET summary = ?, last_enriched = datetime('now')
|
|
177
|
+
WHERE id = ?
|
|
178
|
+
`).run(newSummary, item.id);
|
|
179
|
+
summarized++;
|
|
180
|
+
}
|
|
181
|
+
if (queueMap.has(itemId))
|
|
182
|
+
markProcessed(sleep, queueMap.get(itemId));
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
errors.push(`summarize ${itemId}: ${String(err)}`);
|
|
186
|
+
if (queueMap.has(itemId)) {
|
|
187
|
+
sleep.prepare(`
|
|
188
|
+
UPDATE maintenance_queue
|
|
189
|
+
SET processed_at = datetime('now'), error_message = ?
|
|
190
|
+
WHERE id = ?
|
|
191
|
+
`).run(String(err), queueMap.get(itemId));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
console.warn('[brain-core/sleep/summarize] step failed', { err: String(err) });
|
|
198
|
+
errors.push(`summarize step: ${String(err)}`);
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
count: summarized,
|
|
202
|
+
durationMs: Date.now() - startTime,
|
|
203
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=summarize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarize.js","sourceRoot":"","sources":["../../../src/sleep/steps/summarize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag step — port of KAD's sleep/steps/tag.ts.
|
|
3
|
+
*
|
|
4
|
+
* Refreshes stale/missing tags via Claude Haiku. Capped at maxTagsPerRun
|
|
5
|
+
* per cycle to control LLM cost. Pulls source content from disk when
|
|
6
|
+
* source_path resolves to a readable file, otherwise falls back to the
|
|
7
|
+
* stored summary/title.
|
|
8
|
+
*/
|
|
9
|
+
import type { TenantContext } from '@kybernesis/brain-contracts';
|
|
10
|
+
import type { SleepConfig } from '../config.js';
|
|
11
|
+
export interface TagResult {
|
|
12
|
+
count: number;
|
|
13
|
+
errors?: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function runTagStep(t: TenantContext, config: SleepConfig): Promise<TagResult>;
|
|
16
|
+
//# sourceMappingURL=tag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../../src/sleep/steps/tag.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,UAAU,CAC9B,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,SAAS,CAAC,CA+EpB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag step — port of KAD's sleep/steps/tag.ts.
|
|
3
|
+
*
|
|
4
|
+
* Refreshes stale/missing tags via Claude Haiku. Capped at maxTagsPerRun
|
|
5
|
+
* per cycle to control LLM cost. Pulls source content from disk when
|
|
6
|
+
* source_path resolves to a readable file, otherwise falls back to the
|
|
7
|
+
* stored summary/title.
|
|
8
|
+
*/
|
|
9
|
+
import { promises as fs } from 'node:fs';
|
|
10
|
+
import { getDb } from '@kybernesis/brain-storage-sqlite';
|
|
11
|
+
import { callClaude } from '../../claude-call.js';
|
|
12
|
+
export async function runTagStep(t, config) {
|
|
13
|
+
if (!config.enableTagging)
|
|
14
|
+
return { count: 0 };
|
|
15
|
+
const db = getDb(t, 'timeline');
|
|
16
|
+
const staleDate = new Date(Date.now() - config.tagStaleDays * 24 * 60 * 60 * 1000).toISOString();
|
|
17
|
+
let tagged = 0;
|
|
18
|
+
const errors = [];
|
|
19
|
+
try {
|
|
20
|
+
const items = db.prepare(`
|
|
21
|
+
SELECT id, source_path, title, summary, tags_json, topics_json
|
|
22
|
+
FROM timeline_events
|
|
23
|
+
WHERE (last_enriched IS NULL OR last_enriched < ?)
|
|
24
|
+
OR (tags_json IS NULL OR tags_json = '[]')
|
|
25
|
+
ORDER BY priority DESC
|
|
26
|
+
LIMIT ?
|
|
27
|
+
`).all(staleDate, config.maxTagsPerRun);
|
|
28
|
+
if (items.length === 0)
|
|
29
|
+
return { count: 0 };
|
|
30
|
+
for (const item of items) {
|
|
31
|
+
try {
|
|
32
|
+
let content = item.summary || item.title || '';
|
|
33
|
+
if (item.source_path && !item.source_path.startsWith('channel://')) {
|
|
34
|
+
try {
|
|
35
|
+
const fileContent = await fs.readFile(item.source_path, 'utf-8');
|
|
36
|
+
content = fileContent.slice(0, 3000);
|
|
37
|
+
}
|
|
38
|
+
catch { /* fall back to summary */ }
|
|
39
|
+
}
|
|
40
|
+
if (!content || content.length < 50)
|
|
41
|
+
continue;
|
|
42
|
+
const responseText = await callClaude(`Generate 3-7 relevant tags for this content. Return only a JSON array of lowercase strings, no explanation.
|
|
43
|
+
|
|
44
|
+
Content:
|
|
45
|
+
${content}
|
|
46
|
+
|
|
47
|
+
Example response: ["meeting", "pricing", "strategy", "planning"]`, { model: 'haiku', maxTokens: 500 });
|
|
48
|
+
const jsonMatch = (responseText ?? '').match(/\[[\s\S]*?\]/);
|
|
49
|
+
if (!jsonMatch)
|
|
50
|
+
continue;
|
|
51
|
+
let tags;
|
|
52
|
+
try {
|
|
53
|
+
tags = JSON.parse(jsonMatch[0]);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(tags) && tags.length > 0) {
|
|
59
|
+
const rawTopics = JSON.parse(item.topics_json || '[]');
|
|
60
|
+
const existingTopics = Array.isArray(rawTopics) ? rawTopics : [];
|
|
61
|
+
const allTags = [...new Set([
|
|
62
|
+
...tags.filter((x) => typeof x === 'string').map(s => s.toLowerCase()),
|
|
63
|
+
...existingTopics.map(s => s.toLowerCase()),
|
|
64
|
+
])];
|
|
65
|
+
db.prepare(`
|
|
66
|
+
UPDATE timeline_events
|
|
67
|
+
SET tags_json = ?, last_enriched = datetime('now')
|
|
68
|
+
WHERE id = ?
|
|
69
|
+
`).run(JSON.stringify(allTags), item.id);
|
|
70
|
+
tagged++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
errors.push(`tag item ${item.id}: ${String(err)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.warn('[brain-core/sleep/tag] step failed', { err: String(err) });
|
|
80
|
+
errors.push(`tag step: ${String(err)}`);
|
|
81
|
+
}
|
|
82
|
+
return { count: tagged, errors: errors.length > 0 ? errors : undefined };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.js","sourceRoot":"","sources":["../../../src/sleep/steps/tag.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier step — port of KAD's sleep/steps/tier.ts.
|
|
3
|
+
*
|
|
4
|
+
* Promotes/demotes timeline events between hot/warm/archive tiers.
|
|
5
|
+
*
|
|
6
|
+
* Bug B11A regression-watchpoint: hot promotion uses **OR across 5 signals**
|
|
7
|
+
* (priority threshold OR low decay OR recent access OR relationshipScore OR
|
|
8
|
+
* edgeCount). A v1 port had AND across these signals, which dropped most
|
|
9
|
+
* promotions — the port-faithful library carries KAD's OR shape verbatim.
|
|
10
|
+
*/
|
|
11
|
+
import type { TenantContext } from '@kybernesis/brain-contracts';
|
|
12
|
+
import type { SleepConfig } from '../config.js';
|
|
13
|
+
export interface TierResult {
|
|
14
|
+
count: number;
|
|
15
|
+
errors?: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function runTierStep(t: TenantContext, config: SleepConfig): Promise<TierResult>;
|
|
18
|
+
//# sourceMappingURL=tier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.d.ts","sourceRoot":"","sources":["../../../src/sleep/steps/tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,WAAW,CAC/B,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,CAAC,CA6FrB"}
|