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
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.4.1
|
package/package.json
CHANGED
package/src/cli/auto-setup.ts
CHANGED
|
@@ -8,6 +8,14 @@ function getDefaultEnv(vaultPath: string): string {
|
|
|
8
8
|
VAULT_PATH=${vaultPath}
|
|
9
9
|
LOG_LEVEL=info
|
|
10
10
|
NODE_ENV=production
|
|
11
|
+
|
|
12
|
+
# ChromaDB Configuration
|
|
13
|
+
# Start ChromaDB server: claude-brain chroma start
|
|
14
|
+
# Install ChromaDB: claude-brain chroma install
|
|
15
|
+
CHROMA_MODE=client-server
|
|
16
|
+
CHROMA_HOST=localhost
|
|
17
|
+
CHROMA_PORT=8000
|
|
18
|
+
CHROMA_EMBEDDING_PROVIDER=transformers
|
|
11
19
|
`
|
|
12
20
|
}
|
|
13
21
|
|
package/src/cli/bin.ts
CHANGED
|
@@ -31,6 +31,7 @@ function printHelp() {
|
|
|
31
31
|
['install', 'Register as MCP server in Claude Code'],
|
|
32
32
|
['uninstall', 'Remove MCP server from Claude Code'],
|
|
33
33
|
['update', 'Update package and refresh CLAUDE.md'],
|
|
34
|
+
['chroma', 'Manage ChromaDB server (start/stop/status)'],
|
|
34
35
|
['health', 'Run health checks'],
|
|
35
36
|
['diagnose', 'Run diagnostics'],
|
|
36
37
|
['version', 'Show version'],
|
|
@@ -58,6 +59,7 @@ function printHelp() {
|
|
|
58
59
|
` ${dimText('claude-brain setup')} ${dimText('Configure Claude Brain')}`,
|
|
59
60
|
` ${dimText('claude-brain install')} ${dimText('Register with Claude Code')}`,
|
|
60
61
|
` ${dimText('claude-brain update')} ${dimText('Update to latest version')}`,
|
|
62
|
+
` ${dimText('claude-brain chroma start')} ${dimText('Start ChromaDB server')}`,
|
|
61
63
|
` ${dimText('claude-brain health')} ${dimText('Check system health')}`,
|
|
62
64
|
'',
|
|
63
65
|
theme.bold('Environment:'),
|
|
@@ -102,6 +104,12 @@ async function main() {
|
|
|
102
104
|
break
|
|
103
105
|
}
|
|
104
106
|
|
|
107
|
+
case 'chroma': {
|
|
108
|
+
const { runChroma } = await import('./commands/chroma')
|
|
109
|
+
await runChroma()
|
|
110
|
+
break
|
|
111
|
+
}
|
|
112
|
+
|
|
105
113
|
case 'health': {
|
|
106
114
|
const { runHealthCheck } = await import('@/health')
|
|
107
115
|
await runHealthCheck()
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChromaDB Management Command
|
|
3
|
+
* Start, stop, and manage the ChromaDB server for Claude Brain
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { spawn, execSync } from 'node:child_process'
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'
|
|
8
|
+
import { join } from 'node:path'
|
|
9
|
+
import { getHomePaths } from '@/config/home'
|
|
10
|
+
import {
|
|
11
|
+
theme, heading, successText, errorText, warningText, dimText,
|
|
12
|
+
infoPanel,
|
|
13
|
+
} from '@/cli/ui/index.js'
|
|
14
|
+
|
|
15
|
+
const PID_FILENAME = 'chroma.pid'
|
|
16
|
+
const DEFAULT_PORT = '8000'
|
|
17
|
+
|
|
18
|
+
function getPidFilePath(): string {
|
|
19
|
+
const paths = getHomePaths()
|
|
20
|
+
return join(paths.data, PID_FILENAME)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getChromaDataPath(): string {
|
|
24
|
+
const paths = getHomePaths()
|
|
25
|
+
return paths.chroma
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isChromaCliInstalled(): boolean {
|
|
29
|
+
try {
|
|
30
|
+
execSync('chroma --version', { stdio: 'pipe', timeout: 5000 })
|
|
31
|
+
return true
|
|
32
|
+
} catch {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getChromaVersion(): string {
|
|
38
|
+
try {
|
|
39
|
+
return execSync('chroma --version', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 }).trim()
|
|
40
|
+
} catch {
|
|
41
|
+
return 'unknown'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isPythonInstalled(): { installed: boolean; cmd: string } {
|
|
46
|
+
for (const cmd of ['python3', 'python']) {
|
|
47
|
+
try {
|
|
48
|
+
execSync(`${cmd} --version`, { stdio: 'pipe', timeout: 5000 })
|
|
49
|
+
return { installed: true, cmd }
|
|
50
|
+
} catch {
|
|
51
|
+
// try next
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { installed: false, cmd: 'python3' }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getRunningPid(): number | null {
|
|
58
|
+
const pidPath = getPidFilePath()
|
|
59
|
+
if (!existsSync(pidPath)) return null
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const pid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10)
|
|
63
|
+
if (isNaN(pid)) {
|
|
64
|
+
unlinkSync(pidPath)
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
// Signal 0 tests if process exists without killing it
|
|
68
|
+
process.kill(pid, 0)
|
|
69
|
+
return pid
|
|
70
|
+
} catch {
|
|
71
|
+
// Process not running, clean up stale PID file
|
|
72
|
+
try { unlinkSync(pidPath) } catch {}
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isChromaReachable(): boolean {
|
|
78
|
+
try {
|
|
79
|
+
execSync(`curl -sf http://localhost:${DEFAULT_PORT}/api/v1/heartbeat`, {
|
|
80
|
+
stdio: 'pipe',
|
|
81
|
+
timeout: 3000
|
|
82
|
+
})
|
|
83
|
+
return true
|
|
84
|
+
} catch {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function sleep(ms: number): Promise<void> {
|
|
90
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ── Subcommands ───────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
async function chromaStart(): Promise<void> {
|
|
96
|
+
console.log()
|
|
97
|
+
console.log(heading('Starting ChromaDB Server'))
|
|
98
|
+
console.log()
|
|
99
|
+
|
|
100
|
+
// Check if already running
|
|
101
|
+
const existingPid = getRunningPid()
|
|
102
|
+
if (existingPid) {
|
|
103
|
+
console.log(warningText(`ChromaDB is already running (PID: ${existingPid})`))
|
|
104
|
+
console.log()
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isChromaReachable()) {
|
|
109
|
+
console.log(warningText('A ChromaDB server is already running on port ' + DEFAULT_PORT))
|
|
110
|
+
console.log()
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check if chroma CLI is installed
|
|
115
|
+
if (!isChromaCliInstalled()) {
|
|
116
|
+
console.log(errorText('ChromaDB CLI is not installed.'))
|
|
117
|
+
console.log()
|
|
118
|
+
console.log(dimText('Install it with:'))
|
|
119
|
+
console.log(` ${theme.primary('pip install chromadb')}`)
|
|
120
|
+
console.log()
|
|
121
|
+
console.log(dimText('Or run:'))
|
|
122
|
+
console.log(` ${theme.primary('claude-brain chroma install')}`)
|
|
123
|
+
console.log()
|
|
124
|
+
process.exit(1)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const dataPath = getChromaDataPath()
|
|
128
|
+
|
|
129
|
+
console.log(dimText(`Data path: ${dataPath}`))
|
|
130
|
+
console.log(dimText(`Port: ${DEFAULT_PORT}`))
|
|
131
|
+
console.log()
|
|
132
|
+
|
|
133
|
+
// Start ChromaDB server in background
|
|
134
|
+
const child = spawn('chroma', ['run', '--path', dataPath, '--port', DEFAULT_PORT], {
|
|
135
|
+
detached: true,
|
|
136
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
137
|
+
env: { ...process.env }
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const pid = child.pid
|
|
141
|
+
if (!pid) {
|
|
142
|
+
console.log(errorText('Failed to start ChromaDB server — no PID returned.'))
|
|
143
|
+
console.log()
|
|
144
|
+
process.exit(1)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Detach the child process so it runs independently
|
|
148
|
+
child.unref()
|
|
149
|
+
|
|
150
|
+
// Save PID file
|
|
151
|
+
writeFileSync(getPidFilePath(), String(pid), 'utf-8')
|
|
152
|
+
|
|
153
|
+
// Capture early output for error detection
|
|
154
|
+
let startupOutput = ''
|
|
155
|
+
child.stderr?.on('data', (chunk: Buffer) => {
|
|
156
|
+
startupOutput += chunk.toString()
|
|
157
|
+
})
|
|
158
|
+
child.stdout?.on('data', (chunk: Buffer) => {
|
|
159
|
+
startupOutput += chunk.toString()
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
// Wait up to 15 seconds for server to become reachable
|
|
163
|
+
let ready = false
|
|
164
|
+
for (let i = 0; i < 30; i++) {
|
|
165
|
+
await sleep(500)
|
|
166
|
+
if (isChromaReachable()) {
|
|
167
|
+
ready = true
|
|
168
|
+
break
|
|
169
|
+
}
|
|
170
|
+
// Check if process exited early
|
|
171
|
+
try {
|
|
172
|
+
process.kill(pid, 0)
|
|
173
|
+
} catch {
|
|
174
|
+
break
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (ready) {
|
|
179
|
+
console.log(successText(`ChromaDB server started (PID: ${pid})`))
|
|
180
|
+
console.log()
|
|
181
|
+
console.log(dimText('The server is running in the background.'))
|
|
182
|
+
console.log(dimText('Stop it with: ') + theme.primary('claude-brain chroma stop'))
|
|
183
|
+
} else {
|
|
184
|
+
// Check if process is still alive
|
|
185
|
+
let alive = false
|
|
186
|
+
try {
|
|
187
|
+
process.kill(pid, 0)
|
|
188
|
+
alive = true
|
|
189
|
+
} catch {}
|
|
190
|
+
|
|
191
|
+
if (alive) {
|
|
192
|
+
console.log(warningText('ChromaDB server started but not yet responding.'))
|
|
193
|
+
console.log(dimText(`PID: ${pid} — it may still be initializing.`))
|
|
194
|
+
console.log(dimText('Check with: ') + theme.primary('claude-brain chroma status'))
|
|
195
|
+
} else {
|
|
196
|
+
console.log(errorText('ChromaDB server failed to start.'))
|
|
197
|
+
if (startupOutput) {
|
|
198
|
+
console.log(dimText('Output:'))
|
|
199
|
+
console.log(dimText(startupOutput.slice(0, 500)))
|
|
200
|
+
}
|
|
201
|
+
try { unlinkSync(getPidFilePath()) } catch {}
|
|
202
|
+
process.exit(1)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
console.log()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function chromaStop(): Promise<void> {
|
|
209
|
+
console.log()
|
|
210
|
+
console.log(heading('Stopping ChromaDB Server'))
|
|
211
|
+
console.log()
|
|
212
|
+
|
|
213
|
+
const pid = getRunningPid()
|
|
214
|
+
if (!pid) {
|
|
215
|
+
if (isChromaReachable()) {
|
|
216
|
+
console.log(warningText('A ChromaDB server is running on port ' + DEFAULT_PORT + ' but was not started by claude-brain.'))
|
|
217
|
+
console.log(dimText('Kill it manually if needed.'))
|
|
218
|
+
} else {
|
|
219
|
+
console.log(dimText('No ChromaDB server is currently running.'))
|
|
220
|
+
}
|
|
221
|
+
console.log()
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
process.kill(pid, 'SIGTERM')
|
|
227
|
+
|
|
228
|
+
// Wait up to 5 seconds for graceful shutdown
|
|
229
|
+
for (let i = 0; i < 10; i++) {
|
|
230
|
+
await sleep(500)
|
|
231
|
+
try {
|
|
232
|
+
process.kill(pid, 0)
|
|
233
|
+
} catch {
|
|
234
|
+
// Process exited
|
|
235
|
+
break
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Force kill if still running
|
|
240
|
+
try {
|
|
241
|
+
process.kill(pid, 0)
|
|
242
|
+
// Still alive, force kill
|
|
243
|
+
process.kill(pid, 'SIGKILL')
|
|
244
|
+
} catch {
|
|
245
|
+
// Already dead, good
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try { unlinkSync(getPidFilePath()) } catch {}
|
|
249
|
+
|
|
250
|
+
console.log(successText(`ChromaDB server stopped (PID: ${pid})`))
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.log(errorText(`Failed to stop ChromaDB: ${error instanceof Error ? error.message : String(error)}`))
|
|
253
|
+
try { unlinkSync(getPidFilePath()) } catch {}
|
|
254
|
+
}
|
|
255
|
+
console.log()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function chromaStatus(): Promise<void> {
|
|
259
|
+
console.log()
|
|
260
|
+
|
|
261
|
+
const pid = getRunningPid()
|
|
262
|
+
const reachable = isChromaReachable()
|
|
263
|
+
const installed = isChromaCliInstalled()
|
|
264
|
+
const version = installed ? getChromaVersion() : 'N/A'
|
|
265
|
+
const dataPath = getChromaDataPath()
|
|
266
|
+
const dataExists = existsSync(dataPath)
|
|
267
|
+
|
|
268
|
+
const items: Record<string, string> = {
|
|
269
|
+
'Installed': installed ? `Yes (${version})` : 'No',
|
|
270
|
+
'Server': reachable ? `Running (port ${DEFAULT_PORT})` : 'Not running',
|
|
271
|
+
'Managed PID': pid ? String(pid) : 'None',
|
|
272
|
+
'Data Path': dataPath,
|
|
273
|
+
'Data Exists': dataExists ? 'Yes' : 'No',
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
console.log(infoPanel('ChromaDB Status', items))
|
|
277
|
+
|
|
278
|
+
if (!installed) {
|
|
279
|
+
console.log()
|
|
280
|
+
console.log(warningText('ChromaDB is not installed.'))
|
|
281
|
+
console.log(dimText('Install with: ') + theme.primary('claude-brain chroma install'))
|
|
282
|
+
} else if (!reachable) {
|
|
283
|
+
console.log()
|
|
284
|
+
console.log(dimText('Start the server with: ') + theme.primary('claude-brain chroma start'))
|
|
285
|
+
}
|
|
286
|
+
console.log()
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function chromaInstall(): Promise<void> {
|
|
290
|
+
console.log()
|
|
291
|
+
console.log(heading('Installing ChromaDB'))
|
|
292
|
+
console.log()
|
|
293
|
+
|
|
294
|
+
if (isChromaCliInstalled()) {
|
|
295
|
+
const version = getChromaVersion()
|
|
296
|
+
console.log(successText(`ChromaDB is already installed (${version}).`))
|
|
297
|
+
console.log()
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const python = isPythonInstalled()
|
|
302
|
+
if (!python.installed) {
|
|
303
|
+
console.log(errorText('Python 3 is required to install ChromaDB.'))
|
|
304
|
+
console.log()
|
|
305
|
+
console.log(dimText('Install Python 3 first:'))
|
|
306
|
+
console.log(` ${theme.primary('macOS:')} brew install python3`)
|
|
307
|
+
console.log(` ${theme.primary('Ubuntu:')} sudo apt install python3 python3-pip`)
|
|
308
|
+
console.log(` ${theme.primary('Windows:')} https://python.org/downloads`)
|
|
309
|
+
console.log()
|
|
310
|
+
process.exit(1)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
console.log(dimText(`Found ${python.cmd}. Installing chromadb via pip...`))
|
|
314
|
+
console.log()
|
|
315
|
+
|
|
316
|
+
const pipCommands = python.cmd === 'python3'
|
|
317
|
+
? ['pip3 install chromadb', 'python3 -m pip install chromadb']
|
|
318
|
+
: ['pip install chromadb', 'python -m pip install chromadb']
|
|
319
|
+
|
|
320
|
+
let installed = false
|
|
321
|
+
for (const cmd of pipCommands) {
|
|
322
|
+
try {
|
|
323
|
+
execSync(cmd, { stdio: 'inherit', timeout: 300_000 })
|
|
324
|
+
installed = true
|
|
325
|
+
break
|
|
326
|
+
} catch {
|
|
327
|
+
// Try next command
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
console.log()
|
|
332
|
+
if (installed) {
|
|
333
|
+
console.log(successText('ChromaDB installed successfully!'))
|
|
334
|
+
console.log()
|
|
335
|
+
console.log(dimText('Start the server with: ') + theme.primary('claude-brain chroma start'))
|
|
336
|
+
} else {
|
|
337
|
+
console.log(errorText('Failed to install ChromaDB.'))
|
|
338
|
+
console.log(dimText('Try installing manually:'))
|
|
339
|
+
console.log(` ${theme.primary('pip install chromadb')}`)
|
|
340
|
+
process.exit(1)
|
|
341
|
+
}
|
|
342
|
+
console.log()
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── Help ──────────────────────────────────────────────────
|
|
346
|
+
|
|
347
|
+
function printChromaHelp(): void {
|
|
348
|
+
console.log()
|
|
349
|
+
console.log(heading('ChromaDB Management'))
|
|
350
|
+
console.log()
|
|
351
|
+
console.log(dimText('ChromaDB provides vector storage for semantic search,'))
|
|
352
|
+
console.log(dimText('knowledge graph, and advanced intelligence features.'))
|
|
353
|
+
console.log()
|
|
354
|
+
|
|
355
|
+
const commands = [
|
|
356
|
+
['start', 'Start ChromaDB server in background'],
|
|
357
|
+
['stop', 'Stop the running ChromaDB server'],
|
|
358
|
+
['status', 'Show ChromaDB server status'],
|
|
359
|
+
['install', 'Install ChromaDB (requires Python 3)'],
|
|
360
|
+
]
|
|
361
|
+
|
|
362
|
+
const cmdLines = commands
|
|
363
|
+
.map(([cmd, desc]) => ` ${theme.primary(cmd!.padEnd(12))} ${dimText(desc!)}`)
|
|
364
|
+
.join('\n')
|
|
365
|
+
|
|
366
|
+
console.log(theme.bold('Commands:'))
|
|
367
|
+
console.log(cmdLines)
|
|
368
|
+
console.log()
|
|
369
|
+
|
|
370
|
+
console.log(theme.bold('Usage:'))
|
|
371
|
+
console.log(` ${dimText('claude-brain chroma install')} ${dimText('Install ChromaDB')}`)
|
|
372
|
+
console.log(` ${dimText('claude-brain chroma start')} ${dimText('Start the server')}`)
|
|
373
|
+
console.log(` ${dimText('claude-brain chroma status')} ${dimText('Check if running')}`)
|
|
374
|
+
console.log(` ${dimText('claude-brain chroma stop')} ${dimText('Stop the server')}`)
|
|
375
|
+
console.log()
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// ── Entry Point ───────────────────────────────────────────
|
|
379
|
+
|
|
380
|
+
export async function runChroma(): Promise<void> {
|
|
381
|
+
const subcommand = process.argv[3] || 'help'
|
|
382
|
+
|
|
383
|
+
switch (subcommand) {
|
|
384
|
+
case 'start':
|
|
385
|
+
await chromaStart()
|
|
386
|
+
break
|
|
387
|
+
case 'stop':
|
|
388
|
+
await chromaStop()
|
|
389
|
+
break
|
|
390
|
+
case 'status':
|
|
391
|
+
await chromaStatus()
|
|
392
|
+
break
|
|
393
|
+
case 'install':
|
|
394
|
+
await chromaInstall()
|
|
395
|
+
break
|
|
396
|
+
case 'help':
|
|
397
|
+
case '--help':
|
|
398
|
+
case '-h':
|
|
399
|
+
printChromaHelp()
|
|
400
|
+
break
|
|
401
|
+
default:
|
|
402
|
+
console.log()
|
|
403
|
+
console.log(errorText(`Unknown subcommand: ${subcommand}`))
|
|
404
|
+
printChromaHelp()
|
|
405
|
+
process.exit(1)
|
|
406
|
+
}
|
|
407
|
+
}
|
package/src/config/defaults.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { PartialConfig } from './schema'
|
|
|
3
3
|
/** Default configuration values for Claude Brain */
|
|
4
4
|
export const defaultConfig: PartialConfig = {
|
|
5
5
|
serverName: 'claude-brain',
|
|
6
|
-
serverVersion: '0.
|
|
6
|
+
serverVersion: '0.4.1',
|
|
7
7
|
logLevel: 'info',
|
|
8
8
|
logFilePath: './logs/claude-brain.log',
|
|
9
9
|
dbPath: './data/memory.db',
|
package/src/config/schema.ts
CHANGED
|
@@ -196,7 +196,7 @@ export const ConfigSchema = z.object({
|
|
|
196
196
|
serverName: z.string().default('claude-brain'),
|
|
197
197
|
|
|
198
198
|
/** Server version in semver format */
|
|
199
|
-
serverVersion: z.string().regex(/^\d+\.\d+\.\d+$/, 'Version must be semver format').default('0.
|
|
199
|
+
serverVersion: z.string().regex(/^\d+\.\d+\.\d+$/, 'Version must be semver format').default('0.4.1'),
|
|
200
200
|
|
|
201
201
|
/** Logging level */
|
|
202
202
|
logLevel: LogLevelSchema.default('info'),
|
|
@@ -248,6 +248,26 @@ export class StandardsManager {
|
|
|
248
248
|
'Ignoring error handling',
|
|
249
249
|
'Deep nesting'
|
|
250
250
|
]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
language: 'JavaScript',
|
|
254
|
+
version: 'ES2022+',
|
|
255
|
+
style: 'standard',
|
|
256
|
+
linting: {},
|
|
257
|
+
conventions: [
|
|
258
|
+
'Use strict mode',
|
|
259
|
+
'Prefer const over let',
|
|
260
|
+
'Use async/await over promises',
|
|
261
|
+
'Use optional chaining and nullish coalescing',
|
|
262
|
+
'Add JSDoc comments for public APIs'
|
|
263
|
+
],
|
|
264
|
+
antiPatterns: [
|
|
265
|
+
'Using var',
|
|
266
|
+
'Callback hell',
|
|
267
|
+
'Ignoring error handling',
|
|
268
|
+
'Deep nesting',
|
|
269
|
+
'Mutating function arguments'
|
|
270
|
+
]
|
|
251
271
|
}
|
|
252
272
|
],
|
|
253
273
|
frameworks: [],
|
|
@@ -36,12 +36,12 @@ export class ChromaClientManager {
|
|
|
36
36
|
break
|
|
37
37
|
|
|
38
38
|
case 'client-server':
|
|
39
|
-
if (!this.config.host
|
|
40
|
-
throw new Error('Host
|
|
39
|
+
if (!this.config.host) {
|
|
40
|
+
throw new Error('Host required for client-server mode')
|
|
41
41
|
}
|
|
42
42
|
this.client = new ChromaClient({
|
|
43
43
|
host: this.config.host,
|
|
44
|
-
port: this.config.port,
|
|
44
|
+
port: this.config.port || 8000,
|
|
45
45
|
...authConfig
|
|
46
46
|
})
|
|
47
47
|
break
|
|
@@ -82,8 +82,9 @@ export class ChromaClientManager {
|
|
|
82
82
|
this.isConnected = true
|
|
83
83
|
this.logger.info('ChromaDB client initialized successfully')
|
|
84
84
|
} catch (heartbeatError) {
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
85
|
+
this.isConnected = false
|
|
86
|
+
this.logger.warn({ error: heartbeatError }, 'ChromaDB heartbeat failed')
|
|
87
|
+
throw new Error(`ChromaDB server unreachable: ${heartbeatError instanceof Error ? heartbeatError.message : String(heartbeatError)}`)
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
} catch (error) {
|
|
@@ -35,7 +35,18 @@ export function getChromaConfigFromEnv(): Partial<ChromaConfig> {
|
|
|
35
35
|
|
|
36
36
|
if (process.env.CHROMA_HOST) {
|
|
37
37
|
config.host = process.env.CHROMA_HOST
|
|
38
|
-
|
|
38
|
+
// Only default to cloud if CHROMA_MODE isn't explicitly set
|
|
39
|
+
if (!process.env.CHROMA_MODE) {
|
|
40
|
+
config.mode = 'cloud'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (process.env.CHROMA_MODE) {
|
|
45
|
+
config.mode = process.env.CHROMA_MODE as any
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (process.env.CHROMA_PORT) {
|
|
49
|
+
config.port = parseInt(process.env.CHROMA_PORT, 10)
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
if (process.env.CHROMA_EMBEDDING_PROVIDER) {
|