@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.
Files changed (129) hide show
  1. package/dist/claude-call.d.ts +37 -0
  2. package/dist/claude-call.d.ts.map +1 -0
  3. package/dist/claude-call.js +55 -0
  4. package/dist/claude-call.js.map +1 -0
  5. package/dist/entity-graph.d.ts +79 -0
  6. package/dist/entity-graph.d.ts.map +1 -0
  7. package/dist/entity-graph.js +611 -0
  8. package/dist/entity-graph.js.map +1 -0
  9. package/dist/fact-contradiction.d.ts +25 -0
  10. package/dist/fact-contradiction.d.ts.map +1 -0
  11. package/dist/fact-contradiction.js +109 -0
  12. package/dist/fact-contradiction.js.map +1 -0
  13. package/dist/fact-extractor.d.ts +26 -0
  14. package/dist/fact-extractor.d.ts.map +1 -0
  15. package/dist/fact-extractor.js +98 -0
  16. package/dist/fact-extractor.js.map +1 -0
  17. package/dist/fact-retrieval.d.ts +51 -0
  18. package/dist/fact-retrieval.d.ts.map +1 -0
  19. package/dist/fact-retrieval.js +401 -0
  20. package/dist/fact-retrieval.js.map +1 -0
  21. package/dist/fact-store.d.ts +26 -0
  22. package/dist/fact-store.d.ts.map +1 -0
  23. package/dist/fact-store.js +181 -0
  24. package/dist/fact-store.js.map +1 -0
  25. package/dist/fact-temporal.d.ts +20 -0
  26. package/dist/fact-temporal.d.ts.map +1 -0
  27. package/dist/fact-temporal.js +79 -0
  28. package/dist/fact-temporal.js.map +1 -0
  29. package/dist/fts-sanitizer.d.ts +32 -0
  30. package/dist/fts-sanitizer.d.ts.map +1 -0
  31. package/dist/fts-sanitizer.js +61 -0
  32. package/dist/fts-sanitizer.js.map +1 -0
  33. package/dist/hybrid-search.d.ts +44 -0
  34. package/dist/hybrid-search.d.ts.map +1 -0
  35. package/dist/hybrid-search.js +410 -0
  36. package/dist/hybrid-search.js.map +1 -0
  37. package/dist/index.d.ts +33 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +19 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/ops.d.ts +28 -0
  42. package/dist/ops.d.ts.map +1 -0
  43. package/dist/ops.js +307 -0
  44. package/dist/ops.js.map +1 -0
  45. package/dist/queue.d.ts +13 -0
  46. package/dist/queue.d.ts.map +1 -0
  47. package/dist/queue.js +28 -0
  48. package/dist/queue.js.map +1 -0
  49. package/dist/relationship-extractor.d.ts +38 -0
  50. package/dist/relationship-extractor.d.ts.map +1 -0
  51. package/dist/relationship-extractor.js +119 -0
  52. package/dist/relationship-extractor.js.map +1 -0
  53. package/dist/sleep/config.d.ts +47 -0
  54. package/dist/sleep/config.d.ts.map +1 -0
  55. package/dist/sleep/config.js +46 -0
  56. package/dist/sleep/config.js.map +1 -0
  57. package/dist/sleep/db.d.ts +16 -0
  58. package/dist/sleep/db.d.ts.map +1 -0
  59. package/dist/sleep/db.js +114 -0
  60. package/dist/sleep/db.js.map +1 -0
  61. package/dist/sleep/index.d.ts +69 -0
  62. package/dist/sleep/index.d.ts.map +1 -0
  63. package/dist/sleep/index.js +99 -0
  64. package/dist/sleep/index.js.map +1 -0
  65. package/dist/sleep/steps/consolidate.d.ts +19 -0
  66. package/dist/sleep/steps/consolidate.d.ts.map +1 -0
  67. package/dist/sleep/steps/consolidate.js +74 -0
  68. package/dist/sleep/steps/consolidate.js.map +1 -0
  69. package/dist/sleep/steps/decay.d.ts +19 -0
  70. package/dist/sleep/steps/decay.d.ts.map +1 -0
  71. package/dist/sleep/steps/decay.js +121 -0
  72. package/dist/sleep/steps/decay.js.map +1 -0
  73. package/dist/sleep/steps/entity-hygiene.d.ts +29 -0
  74. package/dist/sleep/steps/entity-hygiene.d.ts.map +1 -0
  75. package/dist/sleep/steps/entity-hygiene.js +452 -0
  76. package/dist/sleep/steps/entity-hygiene.js.map +1 -0
  77. package/dist/sleep/steps/link.d.ts +20 -0
  78. package/dist/sleep/steps/link.d.ts.map +1 -0
  79. package/dist/sleep/steps/link.js +216 -0
  80. package/dist/sleep/steps/link.js.map +1 -0
  81. package/dist/sleep/steps/observe.d.ts +17 -0
  82. package/dist/sleep/steps/observe.d.ts.map +1 -0
  83. package/dist/sleep/steps/observe.js +192 -0
  84. package/dist/sleep/steps/observe.js.map +1 -0
  85. package/dist/sleep/steps/profile.d.ts +15 -0
  86. package/dist/sleep/steps/profile.d.ts.map +1 -0
  87. package/dist/sleep/steps/profile.js +26 -0
  88. package/dist/sleep/steps/profile.js.map +1 -0
  89. package/dist/sleep/steps/reasoning.d.ts +19 -0
  90. package/dist/sleep/steps/reasoning.d.ts.map +1 -0
  91. package/dist/sleep/steps/reasoning.js +173 -0
  92. package/dist/sleep/steps/reasoning.js.map +1 -0
  93. package/dist/sleep/steps/summarize.d.ts +21 -0
  94. package/dist/sleep/steps/summarize.d.ts.map +1 -0
  95. package/dist/sleep/steps/summarize.js +206 -0
  96. package/dist/sleep/steps/summarize.js.map +1 -0
  97. package/dist/sleep/steps/tag.d.ts +16 -0
  98. package/dist/sleep/steps/tag.d.ts.map +1 -0
  99. package/dist/sleep/steps/tag.js +84 -0
  100. package/dist/sleep/steps/tag.js.map +1 -0
  101. package/dist/sleep/steps/tier.d.ts +18 -0
  102. package/dist/sleep/steps/tier.d.ts.map +1 -0
  103. package/dist/sleep/steps/tier.js +112 -0
  104. package/dist/sleep/steps/tier.js.map +1 -0
  105. package/dist/sleep/utils/checkpoint.d.ts +11 -0
  106. package/dist/sleep/utils/checkpoint.d.ts.map +1 -0
  107. package/dist/sleep/utils/checkpoint.js +26 -0
  108. package/dist/sleep/utils/checkpoint.js.map +1 -0
  109. package/dist/sleep/utils/jaccard.d.ts +7 -0
  110. package/dist/sleep/utils/jaccard.d.ts.map +1 -0
  111. package/dist/sleep/utils/jaccard.js +19 -0
  112. package/dist/sleep/utils/jaccard.js.map +1 -0
  113. package/dist/store-conversation.d.ts +29 -0
  114. package/dist/store-conversation.d.ts.map +1 -0
  115. package/dist/store-conversation.js +227 -0
  116. package/dist/store-conversation.js.map +1 -0
  117. package/dist/timeline.d.ts +50 -0
  118. package/dist/timeline.d.ts.map +1 -0
  119. package/dist/timeline.js +389 -0
  120. package/dist/timeline.js.map +1 -0
  121. package/dist/user-profile.d.ts +30 -0
  122. package/dist/user-profile.d.ts.map +1 -0
  123. package/dist/user-profile.js +147 -0
  124. package/dist/user-profile.js.map +1 -0
  125. package/dist/vectors.d.ts +56 -0
  126. package/dist/vectors.d.ts.map +1 -0
  127. package/dist/vectors.js +132 -0
  128. package/dist/vectors.js.map +1 -0
  129. 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"}