claude-brain 0.3.7 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/package.json +1 -1
- package/src/cli/auto-setup.ts +8 -0
- package/src/cli/bin.ts +8 -0
- package/src/cli/commands/chroma.ts +407 -0
- package/src/config/defaults.ts +1 -1
- package/src/config/schema.ts +1 -1
- package/src/context/standards-manager.ts +20 -0
- package/src/memory/chroma/client.ts +6 -5
- package/src/memory/chroma/config.ts +12 -1
- package/src/memory/index.ts +59 -29
- package/src/memory/schema.ts +33 -1
- package/src/memory/store.ts +311 -1
- package/src/server/handlers/tools/analyze-decision-evolution.ts +10 -0
- package/src/server/handlers/tools/detect-trends.ts +10 -0
- package/src/server/handlers/tools/find-cross-project-patterns.ts +10 -0
- package/src/server/handlers/tools/get-decision-timeline.ts +10 -0
- package/src/server/handlers/tools/get-recommendations.ts +10 -0
- package/src/server/handlers/tools/schemas.ts +1 -1
- package/src/server/handlers/tools/search-knowledge-graph.ts +14 -1
- package/src/server/handlers/tools/update-progress.ts +12 -0
- package/src/server/handlers/tools/what-if-analysis.ts +11 -0
- package/src/server/services.ts +14 -9
- package/src/setup/wizard.ts +81 -11
|
@@ -50,6 +50,18 @@ export async function handleUpdateProgress(
|
|
|
50
50
|
completedAt: new Date()
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
+
// Calculate and update completion percentage
|
|
54
|
+
const progressState = await context.progress.getProgress(project_name)
|
|
55
|
+
const totalTasks = progressState.completedTasks.length + progressState.currentTasks.length
|
|
56
|
+
const completionPercentage = totalTasks > 0
|
|
57
|
+
? Math.round((progressState.completedTasks.length / totalTasks) * 100)
|
|
58
|
+
: 0
|
|
59
|
+
|
|
60
|
+
await context.progress.updateProgress(project_name, {
|
|
61
|
+
completionPercentage,
|
|
62
|
+
currentPhase: completionPercentage >= 100 ? 'complete' : 'active'
|
|
63
|
+
})
|
|
64
|
+
|
|
53
65
|
const progressFile = await vault.reader.readMarkdownFile(projectPaths.progress)
|
|
54
66
|
const updatedContent = updateNextStepsSection(progressFile.content, next_steps)
|
|
55
67
|
|
|
@@ -23,6 +23,17 @@ export async function handleWhatIfAnalysis(
|
|
|
23
23
|
const { change, project_name, max_results } = input
|
|
24
24
|
|
|
25
25
|
const memory = getMemoryService()
|
|
26
|
+
|
|
27
|
+
if (!memory.isChromaDBEnabled()) {
|
|
28
|
+
return ResponseFormatter.text(
|
|
29
|
+
`## What-If: "${change}"\n\n` +
|
|
30
|
+
'Unable to perform what-if analysis.\n\n' +
|
|
31
|
+
'Note: ChromaDB is not connected. What-if analysis requires ChromaDB for semantic search across decisions. ' +
|
|
32
|
+
'Decisions stored via SQLite fallback are available through recall_similar. ' +
|
|
33
|
+
'To enable what-if analysis, start a ChromaDB server or configure persistent mode.'
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
const kgService = getKnowledgeGraphService()
|
|
27
38
|
const graph = kgService?.graph || null
|
|
28
39
|
|
package/src/server/services.ts
CHANGED
|
@@ -112,9 +112,9 @@ export async function initializeServices(config: Config, logger: Logger): Promis
|
|
|
112
112
|
await phase12.initialize()
|
|
113
113
|
serviceLogger.info('Phase 12 service initialized')
|
|
114
114
|
|
|
115
|
-
// Initialize Retrieval Service (Phase 13)
|
|
115
|
+
// Initialize Retrieval Service (Phase 13) — requires ChromaDB
|
|
116
116
|
let retrieval: RetrievalService | null = null
|
|
117
|
-
if (config.retrieval?.feedback?.enabled || config.retrieval?.enabled) {
|
|
117
|
+
if ((config.retrieval?.feedback?.enabled || config.retrieval?.enabled) && memory.isChromaDBEnabled()) {
|
|
118
118
|
retrieval = new RetrievalService(
|
|
119
119
|
logger,
|
|
120
120
|
memory.chroma.collections,
|
|
@@ -123,6 +123,8 @@ export async function initializeServices(config: Config, logger: Logger): Promis
|
|
|
123
123
|
)
|
|
124
124
|
await retrieval.initialize()
|
|
125
125
|
serviceLogger.info('Retrieval service initialized')
|
|
126
|
+
} else if (config.retrieval?.enabled && !memory.isChromaDBEnabled()) {
|
|
127
|
+
serviceLogger.warn('Retrieval service requires ChromaDB, skipping initialization')
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
// Initialize Knowledge Graph Service (Phase 14)
|
|
@@ -146,18 +148,21 @@ export async function initializeServices(config: Config, logger: Logger): Promis
|
|
|
146
148
|
|
|
147
149
|
knowledgeGraph = { graph, search, builder, linker }
|
|
148
150
|
|
|
149
|
-
// Migrate existing decisions if graph is empty
|
|
150
|
-
if (graph.getNodeCount() === 0) {
|
|
151
|
+
// Migrate existing decisions if graph is empty (requires ChromaDB)
|
|
152
|
+
if (graph.getNodeCount() === 0 && memory.isChromaDBEnabled()) {
|
|
151
153
|
serviceLogger.info('Empty graph detected, migrating existing decisions...')
|
|
152
154
|
const migrationResult = await builder.migrateExistingDecisions(memory.chroma.collections)
|
|
153
155
|
serviceLogger.info(
|
|
154
156
|
{ processed: migrationResult.processed, errors: migrationResult.errors },
|
|
155
157
|
'Initial graph migration complete'
|
|
156
158
|
)
|
|
159
|
+
} else if (graph.getNodeCount() === 0) {
|
|
160
|
+
serviceLogger.info('Empty graph detected, but ChromaDB unavailable — graph will populate as new decisions are stored')
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
// Hook builder into decision storage for real-time graph population
|
|
160
|
-
|
|
164
|
+
// Uses MemoryManager listener so it works for both ChromaDB and SQLite paths
|
|
165
|
+
memory.addDecisionStoredListener((input) => {
|
|
161
166
|
builder.processDecision(input)
|
|
162
167
|
})
|
|
163
168
|
|
|
@@ -170,9 +175,9 @@ export async function initializeServices(config: Config, logger: Logger): Promis
|
|
|
170
175
|
}
|
|
171
176
|
}
|
|
172
177
|
|
|
173
|
-
// Initialize Episode Manager (Phase 14)
|
|
178
|
+
// Initialize Episode Manager (Phase 14) — requires ChromaDB
|
|
174
179
|
let episodeManager: EpisodeManager | null = null
|
|
175
|
-
if (config.knowledge?.episodic?.enabled !== false) {
|
|
180
|
+
if (config.knowledge?.episodic?.enabled !== false && memory.isChromaDBEnabled()) {
|
|
176
181
|
try {
|
|
177
182
|
episodeManager = new EpisodeManager(
|
|
178
183
|
logger,
|
|
@@ -186,10 +191,10 @@ export async function initializeServices(config: Config, logger: Logger): Promis
|
|
|
186
191
|
}
|
|
187
192
|
}
|
|
188
193
|
|
|
189
|
-
// Initialize Semantic Cache & Precompute (Phase 15)
|
|
194
|
+
// Initialize Semantic Cache & Precompute (Phase 15) — requires ChromaDB
|
|
190
195
|
let semanticCache: SemanticCache | null = null
|
|
191
196
|
let precompute: PrecomputeEngine | null = null
|
|
192
|
-
if (config.advancedIntelligence?.enabled !== false && config.advancedIntelligence?.cache?.enabled !== false) {
|
|
197
|
+
if (config.advancedIntelligence?.enabled !== false && config.advancedIntelligence?.cache?.enabled !== false && memory.isChromaDBEnabled()) {
|
|
193
198
|
try {
|
|
194
199
|
const cacheConfig = config.advancedIntelligence?.cache || {}
|
|
195
200
|
semanticCache = new SemanticCache(logger, {
|
package/src/setup/wizard.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import prompts from 'prompts'
|
|
2
2
|
import fs from 'fs/promises'
|
|
3
3
|
import { existsSync } from 'fs'
|
|
4
|
+
import { execSync } from 'child_process'
|
|
4
5
|
import path from 'path'
|
|
5
6
|
import os from 'os'
|
|
6
7
|
import { fileURLToPath } from 'url'
|
|
@@ -21,6 +22,7 @@ export interface SetupAnswers {
|
|
|
21
22
|
vaultPath: string
|
|
22
23
|
logLevel: string
|
|
23
24
|
enableFileWatch: boolean
|
|
25
|
+
enableChromaDB: boolean
|
|
24
26
|
createSampleProject: boolean
|
|
25
27
|
installClaudeMd: boolean
|
|
26
28
|
}
|
|
@@ -34,7 +36,7 @@ export class SetupWizard {
|
|
|
34
36
|
|
|
35
37
|
async run(): Promise<SetupAnswers> {
|
|
36
38
|
// Step 1: Detect Vaults
|
|
37
|
-
console.log(stepIndicator(1,
|
|
39
|
+
console.log(stepIndicator(1, 6, 'Detecting Obsidian Vaults'))
|
|
38
40
|
await transition()
|
|
39
41
|
|
|
40
42
|
const suggestedPaths = await withSpinner('Scanning for Obsidian vaults', () =>
|
|
@@ -49,7 +51,7 @@ export class SetupWizard {
|
|
|
49
51
|
console.log()
|
|
50
52
|
|
|
51
53
|
// Step 2: Vault Configuration
|
|
52
|
-
console.log(stepIndicator(2,
|
|
54
|
+
console.log(stepIndicator(2, 6, 'Vault Configuration'))
|
|
53
55
|
await transition()
|
|
54
56
|
|
|
55
57
|
const vaultAnswers = await prompts([
|
|
@@ -86,7 +88,7 @@ export class SetupWizard {
|
|
|
86
88
|
const finalVaultPath = vaultAnswers.vaultPath || vaultAnswers.vaultPathChoice
|
|
87
89
|
|
|
88
90
|
// Step 3: Logging
|
|
89
|
-
console.log(stepIndicator(3,
|
|
91
|
+
console.log(stepIndicator(3, 6, 'Logging Configuration'))
|
|
90
92
|
await transition()
|
|
91
93
|
|
|
92
94
|
const loggingAnswers = await prompts({
|
|
@@ -103,7 +105,7 @@ export class SetupWizard {
|
|
|
103
105
|
})
|
|
104
106
|
|
|
105
107
|
// Step 4: Features
|
|
106
|
-
console.log(stepIndicator(4,
|
|
108
|
+
console.log(stepIndicator(4, 6, 'Feature Selection'))
|
|
107
109
|
await transition()
|
|
108
110
|
|
|
109
111
|
const featureAnswers = await prompts([
|
|
@@ -127,14 +129,40 @@ export class SetupWizard {
|
|
|
127
129
|
}
|
|
128
130
|
])
|
|
129
131
|
|
|
130
|
-
// Step 5:
|
|
131
|
-
console.log(stepIndicator(5,
|
|
132
|
+
// Step 5: ChromaDB
|
|
133
|
+
console.log(stepIndicator(5, 6, 'ChromaDB (Vector Database)'))
|
|
134
|
+
await transition()
|
|
135
|
+
|
|
136
|
+
console.log(dimText('ChromaDB enables semantic search, knowledge graph,'))
|
|
137
|
+
console.log(dimText('and advanced intelligence features. Requires Python 3.'))
|
|
138
|
+
console.log()
|
|
139
|
+
|
|
140
|
+
const chromaInstalled = this.isChromaInstalled()
|
|
141
|
+
if (chromaInstalled) {
|
|
142
|
+
console.log(successText('ChromaDB CLI detected'))
|
|
143
|
+
} else {
|
|
144
|
+
console.log(warningText('ChromaDB CLI not found — you can install it later'))
|
|
145
|
+
}
|
|
146
|
+
console.log()
|
|
147
|
+
|
|
148
|
+
const chromaAnswers = await prompts({
|
|
149
|
+
type: 'confirm',
|
|
150
|
+
name: 'enableChromaDB',
|
|
151
|
+
message: chromaInstalled
|
|
152
|
+
? 'Enable ChromaDB for advanced features?'
|
|
153
|
+
: 'Enable ChromaDB? (install later: pip install chromadb)',
|
|
154
|
+
initial: chromaInstalled
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Step 6: Review
|
|
158
|
+
console.log(stepIndicator(6, 6, 'Review Configuration'))
|
|
132
159
|
await transition()
|
|
133
160
|
|
|
134
161
|
const answers: SetupAnswers = {
|
|
135
162
|
vaultPath: finalVaultPath,
|
|
136
163
|
logLevel: loggingAnswers.logLevel ?? 'warn',
|
|
137
164
|
enableFileWatch: featureAnswers.enableFileWatch ?? true,
|
|
165
|
+
enableChromaDB: chromaAnswers.enableChromaDB ?? false,
|
|
138
166
|
createSampleProject: featureAnswers.createSampleProject ?? true,
|
|
139
167
|
installClaudeMd: featureAnswers.installClaudeMd ?? true,
|
|
140
168
|
}
|
|
@@ -143,6 +171,7 @@ export class SetupWizard {
|
|
|
143
171
|
{ label: 'Vault Path', value: answers.vaultPath, status: 'success' },
|
|
144
172
|
{ label: 'Log Level', value: answers.logLevel, status: 'info' },
|
|
145
173
|
{ label: 'File Watching', value: answers.enableFileWatch ? 'Enabled' : 'Disabled', status: answers.enableFileWatch ? 'success' : 'warning' },
|
|
174
|
+
{ label: 'ChromaDB', value: answers.enableChromaDB ? 'Enabled' : 'Disabled', status: answers.enableChromaDB ? 'success' : 'warning' },
|
|
146
175
|
{ label: 'Sample Project', value: answers.createSampleProject ? 'Yes' : 'No', status: 'info' },
|
|
147
176
|
{ label: 'Install CLAUDE.md', value: answers.installClaudeMd ? 'Yes' : 'No', status: 'info' },
|
|
148
177
|
]))
|
|
@@ -191,11 +220,31 @@ export class SetupWizard {
|
|
|
191
220
|
return locations
|
|
192
221
|
}
|
|
193
222
|
|
|
223
|
+
private isChromaInstalled(): boolean {
|
|
224
|
+
try {
|
|
225
|
+
execSync('chroma --version', { stdio: 'pipe', timeout: 5000 })
|
|
226
|
+
return true
|
|
227
|
+
} catch {
|
|
228
|
+
return false
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
194
232
|
async applyConfiguration(answers: SetupAnswers): Promise<void> {
|
|
195
233
|
console.log('\n' + heading('Applying configuration...') + '\n')
|
|
196
234
|
|
|
197
235
|
const homePaths = getHomePaths()
|
|
198
236
|
|
|
237
|
+
const chromaEnvLines = answers.enableChromaDB
|
|
238
|
+
? [
|
|
239
|
+
'',
|
|
240
|
+
'# ChromaDB Configuration',
|
|
241
|
+
'CHROMA_MODE=client-server',
|
|
242
|
+
'CHROMA_HOST=localhost',
|
|
243
|
+
'CHROMA_PORT=8000',
|
|
244
|
+
'CHROMA_EMBEDDING_PROVIDER=transformers',
|
|
245
|
+
].join('\n')
|
|
246
|
+
: ''
|
|
247
|
+
|
|
199
248
|
const envContent = `# Claude Brain Configuration
|
|
200
249
|
VAULT_PATH=${answers.vaultPath}
|
|
201
250
|
LOG_LEVEL=${answers.logLevel}
|
|
@@ -203,6 +252,7 @@ ENABLE_FILE_WATCH=${answers.enableFileWatch}
|
|
|
203
252
|
DB_PATH=./data/memory.db
|
|
204
253
|
LOG_FILE_PATH=./logs/claude-brain.log
|
|
205
254
|
SERVER_NAME=claude-brain
|
|
255
|
+
${chromaEnvLines}
|
|
206
256
|
`
|
|
207
257
|
|
|
208
258
|
await withSpinner('Writing .env configuration', async () => {
|
|
@@ -211,6 +261,7 @@ SERVER_NAME=claude-brain
|
|
|
211
261
|
|
|
212
262
|
await withSpinner('Creating data and log directories', async () => {
|
|
213
263
|
await fs.mkdir(homePaths.data, { recursive: true })
|
|
264
|
+
await fs.mkdir(homePaths.chroma, { recursive: true })
|
|
214
265
|
await fs.mkdir(homePaths.logs, { recursive: true })
|
|
215
266
|
})
|
|
216
267
|
|
|
@@ -229,16 +280,35 @@ SERVER_NAME=claude-brain
|
|
|
229
280
|
}
|
|
230
281
|
}
|
|
231
282
|
|
|
232
|
-
|
|
233
|
-
console.log(box([
|
|
283
|
+
const nextSteps: string[] = [
|
|
234
284
|
heading('Setup complete!'),
|
|
235
285
|
'',
|
|
236
286
|
dimText('Next steps:'),
|
|
237
287
|
` ${theme.primary('1.')} ${theme.bold('claude-brain install')}`,
|
|
238
288
|
` ${dimText('Register as MCP server')}`,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
if (answers.enableChromaDB) {
|
|
292
|
+
nextSteps.push(
|
|
293
|
+
` ${theme.primary('2.')} ${theme.bold('claude-brain chroma install')}`,
|
|
294
|
+
` ${dimText('Install ChromaDB (if not already installed)')}`,
|
|
295
|
+
` ${theme.primary('3.')} ${theme.bold('claude-brain chroma start')}`,
|
|
296
|
+
` ${dimText('Start the ChromaDB server')}`,
|
|
297
|
+
` ${theme.primary('4.')} ${theme.bold('claude-brain health')}`,
|
|
298
|
+
` ${dimText('Verify everything works')}`,
|
|
299
|
+
)
|
|
300
|
+
} else {
|
|
301
|
+
nextSteps.push(
|
|
302
|
+
` ${theme.primary('2.')} ${theme.bold('claude-brain health')}`,
|
|
303
|
+
` ${dimText('Verify everything works')}`,
|
|
304
|
+
'',
|
|
305
|
+
dimText('Optional: Enable ChromaDB later for advanced features:'),
|
|
306
|
+
` ${dimText('claude-brain chroma install && claude-brain chroma start')}`,
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log()
|
|
311
|
+
console.log(box(nextSteps.join('\n'), 'Done'))
|
|
242
312
|
console.log()
|
|
243
313
|
}
|
|
244
314
|
|