claude-brain 0.3.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 (200) hide show
  1. package/README.md +157 -0
  2. package/VERSION +1 -0
  3. package/assets/CLAUDE.md +307 -0
  4. package/bunfig.toml +8 -0
  5. package/package.json +74 -0
  6. package/src/automation/auto-context.ts +240 -0
  7. package/src/automation/decision-detector.ts +452 -0
  8. package/src/automation/index.ts +11 -0
  9. package/src/automation/proactive-recall.ts +373 -0
  10. package/src/automation/project-detector.ts +297 -0
  11. package/src/cli/auto-setup.ts +74 -0
  12. package/src/cli/bin.ts +110 -0
  13. package/src/cli/commands/install-mcp.ts +50 -0
  14. package/src/cli/commands/serve.ts +129 -0
  15. package/src/cli/diagnose.ts +4 -0
  16. package/src/cli/health-check.ts +4 -0
  17. package/src/cli/migrate-chroma.ts +106 -0
  18. package/src/cli/setup.ts +4 -0
  19. package/src/config/defaults.ts +47 -0
  20. package/src/config/home.ts +55 -0
  21. package/src/config/index.ts +7 -0
  22. package/src/config/loader.ts +166 -0
  23. package/src/config/migration.ts +76 -0
  24. package/src/config/schema.ts +257 -0
  25. package/src/config/validator.ts +184 -0
  26. package/src/config/watcher.ts +86 -0
  27. package/src/context/assembler.ts +398 -0
  28. package/src/context/cache-manager.ts +101 -0
  29. package/src/context/formatter.ts +84 -0
  30. package/src/context/hierarchy.ts +85 -0
  31. package/src/context/index.ts +83 -0
  32. package/src/context/progress-tracker.ts +174 -0
  33. package/src/context/standards-manager.ts +267 -0
  34. package/src/context/types.ts +252 -0
  35. package/src/context/validator.ts +58 -0
  36. package/src/cross-project/affinity.ts +162 -0
  37. package/src/cross-project/generalizer.ts +283 -0
  38. package/src/cross-project/index.ts +13 -0
  39. package/src/cross-project/transfer.ts +201 -0
  40. package/src/diagnostics/index.ts +123 -0
  41. package/src/health/index.ts +229 -0
  42. package/src/index.ts +7 -0
  43. package/src/knowledge/entity-extractor.ts +416 -0
  44. package/src/knowledge/graph/builder.ts +159 -0
  45. package/src/knowledge/graph/linker.ts +201 -0
  46. package/src/knowledge/graph/memory-graph.ts +359 -0
  47. package/src/knowledge/graph/schema.ts +99 -0
  48. package/src/knowledge/graph/search.ts +168 -0
  49. package/src/knowledge/relationship-extractor.ts +108 -0
  50. package/src/memory/chroma/client.ts +169 -0
  51. package/src/memory/chroma/collection-manager.ts +94 -0
  52. package/src/memory/chroma/config.ts +46 -0
  53. package/src/memory/chroma/embeddings.ts +153 -0
  54. package/src/memory/chroma/index.ts +82 -0
  55. package/src/memory/chroma/migration.ts +270 -0
  56. package/src/memory/chroma/schemas.ts +69 -0
  57. package/src/memory/chroma/search.ts +315 -0
  58. package/src/memory/chroma/store.ts +694 -0
  59. package/src/memory/consolidation/archiver.ts +164 -0
  60. package/src/memory/consolidation/merger.ts +186 -0
  61. package/src/memory/consolidation/scorer.ts +138 -0
  62. package/src/memory/context-builder.ts +236 -0
  63. package/src/memory/database.ts +169 -0
  64. package/src/memory/embedding-utils.ts +156 -0
  65. package/src/memory/embeddings.ts +226 -0
  66. package/src/memory/episodic/detector.ts +108 -0
  67. package/src/memory/episodic/manager.ts +334 -0
  68. package/src/memory/episodic/summarizer.ts +179 -0
  69. package/src/memory/episodic/types.ts +52 -0
  70. package/src/memory/index.ts +395 -0
  71. package/src/memory/knowledge-extractor.ts +455 -0
  72. package/src/memory/learning.ts +378 -0
  73. package/src/memory/patterns.ts +396 -0
  74. package/src/memory/schema.ts +56 -0
  75. package/src/memory/search.ts +309 -0
  76. package/src/memory/store.ts +344 -0
  77. package/src/memory/types.ts +121 -0
  78. package/src/optimization/index.ts +10 -0
  79. package/src/optimization/precompute.ts +202 -0
  80. package/src/optimization/semantic-cache.ts +207 -0
  81. package/src/orchestrator/coordinator.ts +272 -0
  82. package/src/orchestrator/decision-logger.ts +228 -0
  83. package/src/orchestrator/event-emitter.ts +198 -0
  84. package/src/orchestrator/event-queue.ts +184 -0
  85. package/src/orchestrator/handlers/base-handler.ts +70 -0
  86. package/src/orchestrator/handlers/context-handler.ts +73 -0
  87. package/src/orchestrator/handlers/decision-handler.ts +204 -0
  88. package/src/orchestrator/handlers/index.ts +10 -0
  89. package/src/orchestrator/handlers/status-handler.ts +131 -0
  90. package/src/orchestrator/handlers/task-handler.ts +171 -0
  91. package/src/orchestrator/index.ts +275 -0
  92. package/src/orchestrator/task-parser.ts +284 -0
  93. package/src/orchestrator/types.ts +98 -0
  94. package/src/phase12/index.ts +456 -0
  95. package/src/prediction/context-anticipator.ts +198 -0
  96. package/src/prediction/decision-predictor.ts +184 -0
  97. package/src/prediction/index.ts +13 -0
  98. package/src/prediction/recommender.ts +268 -0
  99. package/src/reasoning/chain-retrieval.ts +247 -0
  100. package/src/reasoning/counterfactual.ts +248 -0
  101. package/src/reasoning/index.ts +13 -0
  102. package/src/reasoning/synthesizer.ts +169 -0
  103. package/src/retrieval/bm25/index.ts +300 -0
  104. package/src/retrieval/bm25/tokenizer.ts +184 -0
  105. package/src/retrieval/feedback/adaptive.ts +223 -0
  106. package/src/retrieval/feedback/index.ts +16 -0
  107. package/src/retrieval/feedback/metrics.ts +223 -0
  108. package/src/retrieval/feedback/store.ts +283 -0
  109. package/src/retrieval/fusion/index.ts +194 -0
  110. package/src/retrieval/fusion/rrf.ts +163 -0
  111. package/src/retrieval/index.ts +12 -0
  112. package/src/retrieval/pipeline.ts +375 -0
  113. package/src/retrieval/query/expander.ts +198 -0
  114. package/src/retrieval/query/index.ts +27 -0
  115. package/src/retrieval/query/intent-classifier.ts +236 -0
  116. package/src/retrieval/query/temporal-parser.ts +295 -0
  117. package/src/retrieval/reranker/index.ts +188 -0
  118. package/src/retrieval/reranker/model.ts +95 -0
  119. package/src/retrieval/service.ts +125 -0
  120. package/src/retrieval/types.ts +162 -0
  121. package/src/scripts/health-check.ts +118 -0
  122. package/src/scripts/setup.ts +122 -0
  123. package/src/server/handlers/call-tool.ts +194 -0
  124. package/src/server/handlers/index.ts +9 -0
  125. package/src/server/handlers/list-tools.ts +18 -0
  126. package/src/server/handlers/tools/analyze-decision-evolution.ts +71 -0
  127. package/src/server/handlers/tools/auto-remember.ts +200 -0
  128. package/src/server/handlers/tools/create-project.ts +135 -0
  129. package/src/server/handlers/tools/detect-trends.ts +80 -0
  130. package/src/server/handlers/tools/find-cross-project-patterns.ts +73 -0
  131. package/src/server/handlers/tools/get-activity-log.ts +194 -0
  132. package/src/server/handlers/tools/get-code-standards.ts +124 -0
  133. package/src/server/handlers/tools/get-corrections.ts +154 -0
  134. package/src/server/handlers/tools/get-decision-timeline.ts +86 -0
  135. package/src/server/handlers/tools/get-episode.ts +93 -0
  136. package/src/server/handlers/tools/get-patterns.ts +158 -0
  137. package/src/server/handlers/tools/get-phase12-status.ts +63 -0
  138. package/src/server/handlers/tools/get-project-context.ts +75 -0
  139. package/src/server/handlers/tools/get-recommendations.ts +65 -0
  140. package/src/server/handlers/tools/index.ts +33 -0
  141. package/src/server/handlers/tools/init-project.ts +710 -0
  142. package/src/server/handlers/tools/list-episodes.ts +80 -0
  143. package/src/server/handlers/tools/list-projects.ts +125 -0
  144. package/src/server/handlers/tools/rate-memory.ts +95 -0
  145. package/src/server/handlers/tools/recall-similar.ts +87 -0
  146. package/src/server/handlers/tools/recognize-pattern.ts +126 -0
  147. package/src/server/handlers/tools/record-correction.ts +125 -0
  148. package/src/server/handlers/tools/remember-decision.ts +153 -0
  149. package/src/server/handlers/tools/schemas.ts +241 -0
  150. package/src/server/handlers/tools/search-knowledge-graph.ts +89 -0
  151. package/src/server/handlers/tools/smart-context.ts +124 -0
  152. package/src/server/handlers/tools/update-progress.ts +114 -0
  153. package/src/server/handlers/tools/what-if-analysis.ts +73 -0
  154. package/src/server/http-api.ts +474 -0
  155. package/src/server/index.ts +40 -0
  156. package/src/server/mcp-server.ts +283 -0
  157. package/src/server/providers/index.ts +7 -0
  158. package/src/server/providers/prompts.ts +327 -0
  159. package/src/server/providers/resources.ts +427 -0
  160. package/src/server/services.ts +388 -0
  161. package/src/server/types.ts +39 -0
  162. package/src/server/utils/error-handler.ts +155 -0
  163. package/src/server/utils/index.ts +13 -0
  164. package/src/server/utils/memory-indicator.ts +83 -0
  165. package/src/server/utils/request-context.ts +122 -0
  166. package/src/server/utils/response-formatter.ts +124 -0
  167. package/src/server/utils/validators.ts +210 -0
  168. package/src/setup/index.ts +22 -0
  169. package/src/setup/wizard.ts +321 -0
  170. package/src/temporal/evolution.ts +197 -0
  171. package/src/temporal/index.ts +16 -0
  172. package/src/temporal/query-processor.ts +190 -0
  173. package/src/temporal/timeline.ts +259 -0
  174. package/src/temporal/trends.ts +263 -0
  175. package/src/tools/index.ts +24 -0
  176. package/src/tools/registry.ts +106 -0
  177. package/src/tools/schemas.test.ts +30 -0
  178. package/src/tools/schemas.ts +907 -0
  179. package/src/tools/types.ts +412 -0
  180. package/src/utils/circuit-breaker.ts +130 -0
  181. package/src/utils/cleanup.ts +34 -0
  182. package/src/utils/error-handler.ts +132 -0
  183. package/src/utils/error-messages.ts +60 -0
  184. package/src/utils/fallback.ts +45 -0
  185. package/src/utils/index.ts +54 -0
  186. package/src/utils/logger-utils.ts +80 -0
  187. package/src/utils/logger.ts +88 -0
  188. package/src/utils/phase12-helper.ts +56 -0
  189. package/src/utils/retry.ts +94 -0
  190. package/src/utils/transaction.ts +63 -0
  191. package/src/vault/frontmatter.ts +264 -0
  192. package/src/vault/index.ts +318 -0
  193. package/src/vault/paths.ts +106 -0
  194. package/src/vault/query.ts +422 -0
  195. package/src/vault/reader.ts +264 -0
  196. package/src/vault/templates.ts +186 -0
  197. package/src/vault/types.ts +73 -0
  198. package/src/vault/watcher.ts +277 -0
  199. package/src/vault/writer.ts +393 -0
  200. package/tsconfig.json +30 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Extractive Summarizer
3
+ * Generates summaries by scoring and selecting key sentences
4
+ */
5
+
6
+ import type { Episode, EpisodeSummary } from './types'
7
+
8
+ interface ScoredSentence {
9
+ text: string
10
+ score: number
11
+ position: number
12
+ }
13
+
14
+ export class ExtractiveSummarizer {
15
+ private briefSize: number
16
+ private detailedSize: number
17
+
18
+ constructor(briefSize: number = 2, detailedSize: number = 8) {
19
+ this.briefSize = briefSize
20
+ this.detailedSize = detailedSize
21
+ }
22
+
23
+ summarize(episode: Episode): EpisodeSummary {
24
+ const allText = episode.messages.map(m => m.content).join('\n')
25
+ const sentences = this.splitSentences(allText)
26
+
27
+ if (sentences.length === 0) {
28
+ return {
29
+ brief: 'Empty episode',
30
+ detailed: 'No messages in this episode.',
31
+ key_topics: [],
32
+ decisions_made: [],
33
+ unresolved_questions: [],
34
+ entity_count: 0
35
+ }
36
+ }
37
+
38
+ // Calculate word frequencies for TF scoring
39
+ const wordFreqs = this.calculateWordFrequencies(allText)
40
+ const totalSentences = sentences.length
41
+
42
+ // Score each sentence
43
+ const scored: ScoredSentence[] = sentences.map((text, position) => ({
44
+ text,
45
+ position,
46
+ score: this.scoreSentence(text, position, totalSentences, wordFreqs)
47
+ }))
48
+
49
+ // Sort by score descending
50
+ const ranked = [...scored].sort((a, b) => b.score - a.score)
51
+
52
+ // Select top sentences for brief and detailed, then re-order by position
53
+ const briefSentences = ranked
54
+ .slice(0, this.briefSize)
55
+ .sort((a, b) => a.position - b.position)
56
+ .map(s => s.text)
57
+
58
+ const detailedSentences = ranked
59
+ .slice(0, this.detailedSize)
60
+ .sort((a, b) => a.position - b.position)
61
+ .map(s => s.text)
62
+
63
+ // Extract key topics from high-frequency words
64
+ const keyTopics = this.extractKeyTopics(wordFreqs)
65
+
66
+ // Find decisions (sentences with decision keywords)
67
+ const decisionKeywords = ['decided', 'chose', 'selected', 'will use', 'going with', 'recommend', 'should use']
68
+ const decisions = sentences.filter(s =>
69
+ decisionKeywords.some(k => s.toLowerCase().includes(k))
70
+ ).slice(0, 5)
71
+
72
+ // Find unresolved questions (last messages with ? that aren't answered)
73
+ const lastMessages = episode.messages.slice(-Math.ceil(episode.messages.length / 2))
74
+ const questions = lastMessages
75
+ .filter(m => m.role === 'user' && m.content.includes('?'))
76
+ .map(m => {
77
+ const qSentences = this.splitSentences(m.content)
78
+ return qSentences.filter(s => s.includes('?'))
79
+ })
80
+ .flat()
81
+ .slice(0, 3)
82
+
83
+ return {
84
+ brief: briefSentences.join(' '),
85
+ detailed: detailedSentences.join(' '),
86
+ key_topics: keyTopics,
87
+ decisions_made: decisions,
88
+ unresolved_questions: questions,
89
+ entity_count: keyTopics.length
90
+ }
91
+ }
92
+
93
+ private splitSentences(text: string): string[] {
94
+ // Split on sentence boundaries
95
+ const raw = text
96
+ .replace(/\n+/g, '. ')
97
+ .split(/(?<=[.!?])\s+/)
98
+ .map(s => s.trim())
99
+ .filter(s => s.length > 10)
100
+
101
+ return raw
102
+ }
103
+
104
+ private calculateWordFrequencies(text: string): Map<string, number> {
105
+ const stopWords = new Set([
106
+ 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
107
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
108
+ 'should', 'can', 'may', 'might', 'to', 'of', 'in', 'for', 'on',
109
+ 'with', 'at', 'by', 'from', 'as', 'and', 'but', 'or', 'not', 'so',
110
+ 'if', 'that', 'this', 'it', 'its', 'i', 'me', 'my', 'we', 'our',
111
+ 'you', 'your', 'he', 'she', 'they', 'them', 'their', 'what', 'which',
112
+ 'who', 'when', 'where', 'how', 'all', 'each', 'both', 'few', 'more',
113
+ 'most', 'other', 'some', 'no', 'only', 'own', 'same', 'than', 'too',
114
+ 'very', 'just', 'about', 'up', 'out', 'off'
115
+ ])
116
+
117
+ const freqs = new Map<string, number>()
118
+ const words = text.toLowerCase()
119
+ .replace(/[^a-z0-9\s-]/g, ' ')
120
+ .split(/\s+/)
121
+ .filter(w => w.length > 2 && !stopWords.has(w))
122
+
123
+ for (const word of words) {
124
+ freqs.set(word, (freqs.get(word) || 0) + 1)
125
+ }
126
+
127
+ return freqs
128
+ }
129
+
130
+ private scoreSentence(
131
+ sentence: string,
132
+ position: number,
133
+ totalSentences: number,
134
+ wordFreqs: Map<string, number>
135
+ ): number {
136
+ let score = 0
137
+
138
+ // 1. TF-based keyword score
139
+ const words = sentence.toLowerCase()
140
+ .replace(/[^a-z0-9\s-]/g, ' ')
141
+ .split(/\s+/)
142
+ .filter(w => w.length > 2)
143
+
144
+ if (words.length === 0) return 0
145
+
146
+ let keywordScore = 0
147
+ for (const word of words) {
148
+ keywordScore += wordFreqs.get(word) || 0
149
+ }
150
+ keywordScore /= words.length // normalize by sentence length
151
+ score += keywordScore * 0.4
152
+
153
+ // 2. Position bonus (first and last sentences score higher)
154
+ const posRatio = position / Math.max(totalSentences - 1, 1)
155
+ const positionScore = posRatio < 0.15 ? 1.0 : posRatio > 0.85 ? 0.8 : 0.3
156
+ score += positionScore * 0.25
157
+
158
+ // 3. Decision keyword boost
159
+ const decisionKeywords = ['decided', 'chose', 'selected', 'recommend', 'should', 'must', 'will use', 'going with', 'use', 'implement', 'adopt']
160
+ const lowerSentence = sentence.toLowerCase()
161
+ const hasDecision = decisionKeywords.some(k => lowerSentence.includes(k))
162
+ if (hasDecision) score += 0.2
163
+
164
+ // 4. Length penalty for very short or very long sentences
165
+ const optimalLength = 20 // words
166
+ const lengthRatio = Math.min(words.length, optimalLength * 2) / optimalLength
167
+ const lengthScore = lengthRatio <= 1 ? lengthRatio : 2 - lengthRatio
168
+ score += Math.max(0, lengthScore) * 0.15
169
+
170
+ return score
171
+ }
172
+
173
+ private extractKeyTopics(wordFreqs: Map<string, number>): string[] {
174
+ return Array.from(wordFreqs.entries())
175
+ .sort(([, a], [, b]) => b - a)
176
+ .slice(0, 10)
177
+ .map(([word]) => word)
178
+ }
179
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Episodic Memory Types
3
+ * Type definitions for the episodic memory system
4
+ */
5
+
6
+ export interface EpisodeMessage {
7
+ role: 'user' | 'assistant' | 'system'
8
+ content: string
9
+ timestamp: string
10
+ token_estimate?: number
11
+ }
12
+
13
+ export interface EpisodeSummary {
14
+ brief: string
15
+ detailed: string
16
+ key_topics: string[]
17
+ decisions_made: string[]
18
+ unresolved_questions: string[]
19
+ entity_count: number
20
+ }
21
+
22
+ export type SessionClassification = 'new_session' | 'continuation' | 'topic_shift'
23
+
24
+ export interface Episode {
25
+ id: string
26
+ project?: string
27
+ status: 'active' | 'completed'
28
+ started_at: string
29
+ ended_at?: string
30
+ messages: EpisodeMessage[]
31
+ summary?: EpisodeSummary
32
+ related_decisions: string[]
33
+ related_patterns: string[]
34
+ related_corrections: string[]
35
+ token_count: number
36
+ message_count: number
37
+ }
38
+
39
+ export interface EpisodeMetadata {
40
+ episode_id: string
41
+ project: string
42
+ status: 'active' | 'completed'
43
+ started_at: string
44
+ ended_at: string
45
+ message_count: number
46
+ token_count: number
47
+ key_topics: string
48
+ brief_summary: string
49
+ related_decisions: string
50
+ related_patterns: string
51
+ related_corrections: string
52
+ }
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Memory System - Main Module
3
+ * Phase 3: Memory and Embedding System
4
+ *
5
+ * Unified memory system manager that combines all components
6
+ */
7
+
8
+ import type { Logger } from 'pino'
9
+ import { MemoryDatabase } from './database'
10
+ import { EmbeddingService } from './embeddings'
11
+ import { MemoryStore } from './store'
12
+ import { SemanticSearch } from './search'
13
+ import { MemoryContextBuilder } from './context-builder'
14
+ import type { MemorySystemStats } from './types'
15
+ import { ChromaManager, DEFAULT_CHROMA_CONFIG, getChromaConfigFromEnv, ChromaMigration, type MigrationOptions } from './chroma'
16
+
17
+ // Re-export all types and classes for external use
18
+ export * from './types'
19
+ export { MemoryDatabase } from './database'
20
+ export { EmbeddingService } from './embeddings'
21
+ export { MemoryStore } from './store'
22
+ export { SemanticSearch } from './search'
23
+ export { MemoryContextBuilder, type ContextOptions } from './context-builder'
24
+ export {
25
+ embeddingToBuffer,
26
+ bufferToEmbedding,
27
+ normalizeEmbedding,
28
+ euclideanDistance,
29
+ cosineSimilarity,
30
+ dotProduct,
31
+ magnitude,
32
+ averageEmbeddings,
33
+ topKSimilar
34
+ } from './embedding-utils'
35
+
36
+ // Phase 12: Advanced Memory Features
37
+ export { PatternRecognizer, type Pattern } from './patterns'
38
+ export { LearningSystem, type Correction, type Preference, type LearningInsights } from './learning'
39
+ export { KnowledgeExtractor, type ExtractedKnowledge, type ExtractionResult } from './knowledge-extractor'
40
+
41
+ /**
42
+ * Unified memory system manager
43
+ * Combines database, embeddings, store, search, and context building
44
+ */
45
+ export class MemoryManager {
46
+ readonly database: MemoryDatabase
47
+ readonly embeddings: EmbeddingService
48
+ readonly contextBuilder: MemoryContextBuilder
49
+ readonly chroma: ChromaManager
50
+
51
+ // Store and search are initialized after database is ready
52
+ private _store: MemoryStore | null = null
53
+ private _search: SemanticSearch | null = null
54
+
55
+ private logger: Logger
56
+ private initialized: boolean = false
57
+ private useChromaDB: boolean = true
58
+
59
+ constructor(
60
+ dbPath: string,
61
+ logger: Logger,
62
+ useChromaDB: boolean = true,
63
+ chromaConfig?: any,
64
+ customEmbeddings?: EmbeddingService
65
+ ) {
66
+ this.logger = logger.child({ component: 'memory-manager' })
67
+ this.useChromaDB = useChromaDB
68
+
69
+ this.database = new MemoryDatabase(dbPath, logger)
70
+ this.embeddings = customEmbeddings || new EmbeddingService(logger)
71
+ this.contextBuilder = new MemoryContextBuilder(logger)
72
+
73
+ const envConfig = getChromaConfigFromEnv()
74
+ const config = { ...DEFAULT_CHROMA_CONFIG, ...envConfig, ...chromaConfig }
75
+ this.chroma = new ChromaManager(logger, config)
76
+ }
77
+
78
+ /**
79
+ * Initialize memory system
80
+ * Must be called before using store or search
81
+ */
82
+ async initialize(): Promise<void> {
83
+ if (this.initialized) {
84
+ this.logger.warn('Memory system already initialized')
85
+ return
86
+ }
87
+
88
+ try {
89
+ this.logger.info('Initializing memory system...')
90
+
91
+ await this.database.initialize()
92
+
93
+ await this.embeddings.initialize()
94
+
95
+ const db = this.database.getDb()
96
+ this._store = new MemoryStore(db, this.embeddings, this.logger)
97
+ this._search = new SemanticSearch(db, this.embeddings, this.logger)
98
+
99
+ if (this.useChromaDB) {
100
+ try {
101
+ await this.chroma.initialize()
102
+ this.logger.info('ChromaDB backend initialized successfully')
103
+ } catch (error) {
104
+ this.logger.warn({ error }, 'Failed to initialize ChromaDB, falling back to SQLite backend')
105
+ this.useChromaDB = false
106
+ }
107
+ }
108
+
109
+ this.initialized = true
110
+ this.logger.info('Memory system initialized successfully')
111
+ } catch (error) {
112
+ this.logger.error({ error }, 'Failed to initialize memory system')
113
+ throw error
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get the memory store (throws if not initialized)
119
+ */
120
+ get store(): MemoryStore {
121
+ if (!this._store) {
122
+ throw new Error('Memory system not initialized. Call initialize() first.')
123
+ }
124
+ return this._store
125
+ }
126
+
127
+ /**
128
+ * Get the semantic search engine (throws if not initialized)
129
+ */
130
+ get search(): SemanticSearch {
131
+ if (!this._search) {
132
+ throw new Error('Memory system not initialized. Call initialize() first.')
133
+ }
134
+ return this._search
135
+ }
136
+
137
+ /**
138
+ * Check if memory system is initialized
139
+ */
140
+ isInitialized(): boolean {
141
+ return this.initialized
142
+ }
143
+
144
+ close(): void {
145
+ if (this.useChromaDB) {
146
+ this.chroma.close()
147
+ }
148
+ this.database.close()
149
+ this._store = null
150
+ this._search = null
151
+ this.initialized = false
152
+ this.logger.info('Memory system closed')
153
+ }
154
+
155
+ /**
156
+ * Get system statistics
157
+ */
158
+ getStats(): MemorySystemStats {
159
+ if (!this.initialized) {
160
+ throw new Error('Memory system not initialized')
161
+ }
162
+
163
+ return {
164
+ database: this.database.getStats(),
165
+ embeddings: this.embeddings.getCacheStats()
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Health check
171
+ */
172
+ async healthCheck(): Promise<boolean> {
173
+ if (!this.initialized) {
174
+ return false
175
+ }
176
+ return this.database.healthCheck()
177
+ }
178
+
179
+ async rememberDecision(
180
+ project: string,
181
+ context: string,
182
+ decision: string,
183
+ reasoning: string,
184
+ options?: { alternatives?: string; tags?: string[] }
185
+ ): Promise<string> {
186
+ if (this.useChromaDB) {
187
+ return this.chroma.store.storeDecision({
188
+ project,
189
+ context,
190
+ decision,
191
+ reasoning,
192
+ alternatives: options?.alternatives,
193
+ tags: options?.tags
194
+ })
195
+ }
196
+ return this.store.storeDecision({
197
+ project,
198
+ context,
199
+ decision,
200
+ reasoning,
201
+ alternatives: options?.alternatives,
202
+ tags: options?.tags
203
+ })
204
+ }
205
+
206
+ /**
207
+ * Get raw search results - routes to ChromaDB when enabled
208
+ * Use this for internal operations that need raw results
209
+ */
210
+ async searchRaw(
211
+ query: string,
212
+ options?: { project?: string; limit?: number; minSimilarity?: number }
213
+ ): Promise<any[]> {
214
+ if (this.useChromaDB) {
215
+ const chromaResults = await this.chroma.search.searchDecisions(query, {
216
+ project: options?.project,
217
+ limit: options?.limit || 5,
218
+ minSimilarity: options?.minSimilarity || 0.5
219
+ })
220
+ // Transform ChromaDB results to match MemorySearchResult structure
221
+ return chromaResults.map(r => ({
222
+ memory: {
223
+ id: r.id,
224
+ project: r.metadata.project || options?.project || 'unknown',
225
+ content: typeof r.content === 'string' ? r.content : JSON.stringify(r.content),
226
+ createdAt: r.metadata.created_at ? new Date(r.metadata.created_at) : new Date(),
227
+ metadata: r.metadata
228
+ },
229
+ similarity: r.similarity,
230
+ decision: r.metadata.decision ? {
231
+ id: r.id,
232
+ project: r.metadata.project || options?.project || 'unknown',
233
+ context: r.metadata.context || '',
234
+ decision: r.metadata.decision || (typeof r.content === 'string' ? r.content : ''),
235
+ reasoning: r.metadata.reasoning || '',
236
+ alternatives: r.metadata.alternatives_considered || '',
237
+ tags: r.metadata.tags || [],
238
+ outcome: r.metadata.outcome,
239
+ createdAt: r.metadata.created_at ? new Date(r.metadata.created_at) : new Date()
240
+ } : undefined
241
+ }))
242
+ } else {
243
+ return await this.search.search(query, {
244
+ project: options?.project,
245
+ limit: options?.limit || 5,
246
+ minSimilarity: options?.minSimilarity || 0.5
247
+ })
248
+ }
249
+ }
250
+
251
+ async recallSimilar(
252
+ query: string,
253
+ options?: { project?: string; limit?: number; minSimilarity?: number }
254
+ ): Promise<string> {
255
+ const results = await this.searchRaw(query, options)
256
+ return this.contextBuilder.buildDecisionContext(results)
257
+ }
258
+
259
+ async getRecommendations(
260
+ currentContext: string,
261
+ project: string,
262
+ limit: number = 3
263
+ ): Promise<string> {
264
+ const results = await this.search.getRecommendations(currentContext, project, limit)
265
+ return this.contextBuilder.buildRecommendationContext(results)
266
+ }
267
+
268
+ async migrateToChromaDB(options: MigrationOptions = {}): Promise<any> {
269
+ if (!this.useChromaDB) {
270
+ throw new Error('ChromaDB is not enabled')
271
+ }
272
+
273
+ const migration = new ChromaMigration(
274
+ this.logger,
275
+ this.database.getDb(),
276
+ this.chroma.store,
277
+ this.chroma.collections
278
+ )
279
+
280
+ return migration.migrate(options)
281
+ }
282
+
283
+ /**
284
+ * Store a pattern in memory
285
+ */
286
+ async storePattern(input: {
287
+ project: string
288
+ pattern_type: 'solution' | 'anti-pattern' | 'best-practice' | 'common-issue'
289
+ description: string
290
+ example?: string
291
+ confidence: number
292
+ context?: string
293
+ }): Promise<string> {
294
+ if (!this.useChromaDB) {
295
+ throw new Error('Pattern storage requires ChromaDB backend')
296
+ }
297
+ return this.chroma.store.storePattern(input)
298
+ }
299
+
300
+ /**
301
+ * Store a correction/lesson learned in memory
302
+ */
303
+ async storeCorrection(input: {
304
+ project: string
305
+ original: string
306
+ correction: string
307
+ reasoning: string
308
+ context?: string
309
+ confidence: number
310
+ }): Promise<string> {
311
+ if (!this.useChromaDB) {
312
+ throw new Error('Correction storage requires ChromaDB backend')
313
+ }
314
+ return this.chroma.store.storeCorrection(input)
315
+ }
316
+
317
+ /**
318
+ * Get patterns for a project
319
+ */
320
+ async getPatterns(
321
+ project?: string,
322
+ options?: {
323
+ pattern_type?: 'solution' | 'anti-pattern' | 'best-practice' | 'common-issue'
324
+ limit?: number
325
+ }
326
+ ): Promise<any[]> {
327
+ if (!this.useChromaDB) {
328
+ throw new Error('Pattern retrieval requires ChromaDB backend')
329
+ }
330
+ if (project) {
331
+ return this.chroma.store.getPatternsByProject(project, options)
332
+ }
333
+ // If no project specified, search all patterns
334
+ return this.chroma.store.searchPatterns('', { limit: options?.limit || 10 })
335
+ }
336
+
337
+ /**
338
+ * Get corrections for a project
339
+ */
340
+ async getCorrections(
341
+ project?: string,
342
+ options?: { limit?: number }
343
+ ): Promise<any[]> {
344
+ if (!this.useChromaDB) {
345
+ throw new Error('Correction retrieval requires ChromaDB backend')
346
+ }
347
+ if (project) {
348
+ return this.chroma.store.getCorrectionsByProject(project, options?.limit || 10)
349
+ }
350
+ // If no project specified, search all corrections
351
+ return this.chroma.store.searchCorrections('', { limit: options?.limit || 10 })
352
+ }
353
+
354
+ /**
355
+ * Search patterns by query
356
+ */
357
+ async searchPatterns(
358
+ query: string,
359
+ options?: {
360
+ project?: string
361
+ pattern_type?: 'solution' | 'anti-pattern' | 'best-practice' | 'common-issue'
362
+ limit?: number
363
+ minSimilarity?: number
364
+ }
365
+ ): Promise<any[]> {
366
+ if (!this.useChromaDB) {
367
+ throw new Error('Pattern search requires ChromaDB backend')
368
+ }
369
+ return this.chroma.store.searchPatterns(query, options)
370
+ }
371
+
372
+ /**
373
+ * Search corrections by query
374
+ */
375
+ async searchCorrections(
376
+ query: string,
377
+ options?: {
378
+ project?: string
379
+ limit?: number
380
+ minSimilarity?: number
381
+ }
382
+ ): Promise<any[]> {
383
+ if (!this.useChromaDB) {
384
+ throw new Error('Correction search requires ChromaDB backend')
385
+ }
386
+ return this.chroma.store.searchCorrections(query, options)
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Create a memory manager instance
392
+ */
393
+ export function createMemoryManager(dbPath: string, logger: Logger): MemoryManager {
394
+ return new MemoryManager(dbPath, logger)
395
+ }