claude-brain 0.30.2 → 0.30.3
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/README.md +241 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +29 -29
- package/package.json +7 -3
- package/packs/backend/node.json +173 -173
- package/packs/core/javascript.json +176 -176
- package/packs/core/typescript.json +222 -222
- package/packs/frontend/react.json +254 -254
- package/packs/meta/testing.json +172 -172
- package/scripts/postinstall.mjs +531 -531
- package/src/automation/decision-detector.ts +452 -452
- package/src/automation/phase12-manager.ts +456 -456
- package/src/automation/proactive-recall.ts +373 -373
- package/src/automation/project-detector.ts +310 -310
- package/src/automation/repo-scanner.ts +210 -205
- package/src/cli/auto-setup.ts +75 -75
- package/src/cli/auto-start.ts +266 -266
- package/src/cli/bin.ts +264 -264
- package/src/cli/commands/autostart.ts +90 -90
- package/src/cli/commands/chroma.ts +578 -577
- package/src/cli/commands/export-training.ts +70 -70
- package/src/cli/commands/export.ts +130 -130
- package/src/cli/commands/git-hook.ts +183 -183
- package/src/cli/commands/hooks.ts +217 -217
- package/src/cli/commands/init.ts +123 -123
- package/src/cli/commands/install-mcp.ts +122 -111
- package/src/cli/commands/models.ts +979 -979
- package/src/cli/commands/pack.ts +200 -200
- package/src/cli/commands/refresh.ts +344 -339
- package/src/cli/commands/reindex.ts +120 -120
- package/src/cli/commands/serve.ts +466 -463
- package/src/cli/commands/start.ts +44 -44
- package/src/cli/commands/status.ts +220 -203
- package/src/cli/commands/uninstall-mcp.ts +45 -41
- package/src/cli/commands/update.ts +130 -124
- package/src/cli/migrate-chroma.ts +106 -106
- package/src/cli/ui/animations.ts +80 -80
- package/src/cli/ui/components.ts +82 -82
- package/src/cli/ui/index.ts +4 -4
- package/src/cli/ui/logo.ts +36 -36
- package/src/cli/ui/theme.ts +55 -55
- package/src/code-intelligence/indexer.ts +352 -352
- package/src/code-intelligence/linker.ts +178 -178
- package/src/code-intelligence/parser.ts +484 -484
- package/src/code-intelligence/query.ts +291 -291
- package/src/code-intelligence/schema.ts +83 -83
- package/src/code-intelligence/types.ts +95 -95
- package/src/config/defaults.ts +52 -52
- package/src/config/home.ts +56 -56
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +192 -192
- package/src/config/schema.ts +446 -415
- package/src/config/validator.ts +182 -182
- package/src/context/assembler.ts +407 -400
- package/src/context/index.ts +79 -79
- package/src/context/progress-tracker.ts +174 -174
- package/src/context/standards-manager.ts +287 -287
- package/src/context/validator.ts +58 -58
- package/src/diagnostics/index.ts +122 -121
- package/src/health/index.ts +233 -232
- package/src/hooks/brain-hook.ts +134 -131
- package/src/hooks/capture.ts +168 -168
- package/src/hooks/claude-code-mastery.md +112 -112
- package/src/hooks/context-hook.ts +260 -245
- package/src/hooks/deduplicator.ts +72 -72
- package/src/hooks/git-capture.ts +109 -109
- package/src/hooks/git-hook-installer.ts +211 -207
- package/src/hooks/index.ts +20 -20
- package/src/hooks/installer.ts +306 -288
- package/src/hooks/interceptor-hook.ts +204 -201
- package/src/hooks/passive-classifier.ts +397 -397
- package/src/hooks/queue.ts +160 -129
- package/src/hooks/session-tracker.ts +312 -312
- package/src/hooks/types.ts +52 -52
- package/src/index.ts +7 -7
- package/src/intelligence/cross-project/generalizer.ts +283 -283
- package/src/intelligence/cross-project/index.ts +7 -7
- package/src/intelligence/hf-downloader.ts +222 -222
- package/src/intelligence/hf-manifest.json +78 -78
- package/src/intelligence/index.ts +24 -24
- package/src/intelligence/inference-router.ts +762 -762
- package/src/intelligence/model-manager.ts +263 -245
- package/src/intelligence/optimization/index.ts +10 -10
- package/src/intelligence/optimization/precompute.ts +202 -202
- package/src/intelligence/optimization/semantic-cache.ts +213 -207
- package/src/intelligence/prediction/index.ts +7 -7
- package/src/intelligence/prediction/recommender.ts +276 -268
- package/src/intelligence/reasoning/chain-retrieval.ts +243 -247
- package/src/intelligence/reasoning/index.ts +7 -7
- package/src/intelligence/temporal/evolution.ts +193 -197
- package/src/intelligence/temporal/index.ts +16 -16
- package/src/intelligence/temporal/query-processor.ts +190 -190
- package/src/intelligence/temporal/timeline.ts +272 -259
- package/src/intelligence/temporal/trends.ts +263 -263
- package/src/intelligence/tokenizer.ts +118 -118
- package/src/knowledge/entity-extractor.ts +447 -443
- package/src/knowledge/graph/builder.ts +185 -185
- package/src/knowledge/graph/linker.ts +201 -201
- package/src/knowledge/graph/memory-graph.ts +359 -359
- package/src/knowledge/graph/schema.ts +99 -99
- package/src/knowledge/graph/search.ts +166 -166
- package/src/knowledge/relationship-extractor.ts +108 -108
- package/src/memory/chroma/client.ts +211 -192
- package/src/memory/chroma/collection-manager.ts +92 -92
- package/src/memory/chroma/config.ts +57 -57
- package/src/memory/chroma/embeddings.ts +177 -175
- package/src/memory/chroma/index.ts +82 -82
- package/src/memory/chroma/migration.ts +270 -270
- package/src/memory/chroma/schemas.ts +69 -69
- package/src/memory/chroma/search.ts +319 -315
- package/src/memory/chroma/store.ts +755 -747
- package/src/memory/compression.ts +121 -121
- package/src/memory/consolidation/archiver.ts +162 -165
- package/src/memory/consolidation/merger.ts +182 -186
- package/src/memory/consolidation/scorer.ts +136 -136
- package/src/memory/database.ts +9 -0
- package/src/memory/dual-write.ts +145 -0
- package/src/memory/embeddings.ts +226 -226
- package/src/memory/episodic/detector.ts +108 -108
- package/src/memory/episodic/manager.ts +347 -351
- package/src/memory/episodic/summarizer.ts +179 -179
- package/src/memory/episodic/types.ts +52 -52
- package/src/memory/fts5-search.ts +692 -633
- package/src/memory/index.ts +943 -1060
- package/src/memory/migrations/add-fts5.ts +118 -108
- package/src/memory/patterns.ts +438 -438
- package/src/memory/pruning.ts +60 -60
- package/src/memory/schema.ts +88 -88
- package/src/memory/store.ts +911 -787
- package/src/orchestrator/handlers/decision-handler.ts +204 -204
- package/src/packs/index.ts +9 -9
- package/src/packs/loader.ts +134 -134
- package/src/packs/manager.ts +204 -204
- package/src/packs/ranker.ts +78 -78
- package/src/packs/types.ts +81 -81
- package/src/phase12/index.ts +5 -5
- package/src/retrieval/bm25/index.ts +300 -297
- package/src/retrieval/bm25/tokenizer.ts +184 -184
- package/src/retrieval/feedback/adaptive.ts +221 -221
- package/src/retrieval/feedback/index.ts +16 -16
- package/src/retrieval/feedback/metrics.ts +221 -221
- package/src/retrieval/feedback/store.ts +283 -283
- package/src/retrieval/fusion/index.ts +194 -194
- package/src/retrieval/fusion/rrf.ts +165 -165
- package/src/retrieval/index.ts +12 -12
- package/src/retrieval/pipeline.ts +375 -375
- package/src/retrieval/query/expander.ts +203 -203
- package/src/retrieval/query/index.ts +27 -27
- package/src/retrieval/query/intent-classifier.ts +252 -252
- package/src/retrieval/query/temporal-parser.ts +295 -295
- package/src/retrieval/reranker/index.ts +189 -188
- package/src/retrieval/reranker/model.ts +99 -95
- package/src/retrieval/service.ts +125 -125
- package/src/retrieval/types.ts +162 -162
- package/src/routing/entity-extractor.ts +454 -454
- package/src/routing/handlers/exploration-handler.ts +369 -0
- package/src/routing/handlers/index.ts +19 -0
- package/src/routing/handlers/memory-handler.ts +273 -0
- package/src/routing/handlers/mutation-handler.ts +241 -0
- package/src/routing/handlers/recall-handler.ts +642 -0
- package/src/routing/handlers/shared.ts +515 -0
- package/src/routing/handlers/types.ts +48 -0
- package/src/routing/intent-classifier.ts +552 -552
- package/src/routing/response-filter.ts +399 -391
- package/src/routing/router.ts +245 -2193
- package/src/routing/search-engine.ts +521 -514
- package/src/routing/types.ts +104 -94
- package/src/scripts/health-check.ts +118 -118
- package/src/scripts/setup.ts +122 -122
- package/src/server/auto-updater.ts +283 -276
- package/src/server/handlers/call-tool.ts +159 -159
- package/src/server/handlers/list-tools.ts +35 -35
- package/src/server/handlers/tools/auto-remember.ts +165 -165
- package/src/server/handlers/tools/brain.ts +86 -86
- package/src/server/handlers/tools/create-project.ts +135 -135
- package/src/server/handlers/tools/get-code-standards.ts +123 -123
- package/src/server/handlers/tools/get-corrections.ts +152 -152
- package/src/server/handlers/tools/get-patterns.ts +156 -156
- package/src/server/handlers/tools/get-project-context.ts +75 -75
- package/src/server/handlers/tools/index.ts +30 -30
- package/src/server/handlers/tools/init-project.ts +756 -756
- package/src/server/handlers/tools/list-projects.ts +126 -126
- package/src/server/handlers/tools/recall-similar.ts +87 -87
- package/src/server/handlers/tools/recognize-pattern.ts +132 -132
- package/src/server/handlers/tools/record-correction.ts +131 -131
- package/src/server/handlers/tools/remember-decision.ts +168 -168
- package/src/server/handlers/tools/schemas.ts +179 -179
- package/src/server/handlers/tools/search-code.ts +122 -122
- package/src/server/handlers/tools/smart-context.ts +146 -146
- package/src/server/handlers/tools/update-progress.ts +131 -131
- package/src/server/http-api.ts +215 -1229
- package/src/server/mcp-proxy.ts +85 -84
- package/src/server/mcp-server.ts +285 -284
- package/src/server/middleware/auth.ts +39 -0
- package/src/server/middleware/error-handler.ts +37 -0
- package/src/server/middleware/rate-limit.ts +53 -0
- package/src/server/middleware/validate.ts +42 -0
- package/src/server/pid-manager.ts +137 -136
- package/src/server/providers/resources.ts +581 -581
- package/src/server/routes/code.ts +228 -0
- package/src/server/routes/context.ts +26 -0
- package/src/server/routes/health.ts +19 -0
- package/src/server/routes/helpers.ts +100 -0
- package/src/server/routes/hooks.ts +197 -0
- package/src/server/routes/mcp.ts +47 -0
- package/src/server/routes/memory.ts +397 -0
- package/src/server/routes/models.ts +96 -0
- package/src/server/routes/projects.ts +89 -0
- package/src/server/routes/types.ts +21 -0
- package/src/server/schemas/api-schemas.ts +202 -0
- package/src/server/services.ts +720 -720
- package/src/server/utils/memory-indicator.ts +84 -84
- package/src/server/utils/response-formatter.ts +129 -129
- package/src/server/web-viewer.ts +1145 -1115
- package/src/setup/index.ts +38 -38
- package/src/tools/registry.ts +115 -115
- package/src/tools/schemas.ts +666 -666
- package/src/tools/types.ts +412 -412
- package/src/training/data-store.ts +320 -298
- package/src/training/retrain-pipeline.ts +399 -394
- package/src/utils/error-handler.ts +136 -136
- package/src/utils/index.ts +58 -58
- package/src/utils/kill-port.ts +55 -53
- package/src/utils/phase12-helper.ts +56 -56
- package/src/utils/safe-path.ts +43 -0
- package/src/utils/timing.ts +47 -47
- package/src/utils/transaction.ts +63 -63
- package/src/vault/index.ts +4 -3
- package/src/vault/paths.ts +106 -106
- package/src/vault/query.ts +4 -1
- package/src/vault/reader.ts +44 -1
- package/src/vault/watcher.ts +24 -1
- package/src/vault/writer.ts +487 -413
- package/skills/persistent-memory/SKILL.md +0 -148
- package/skills/persistent-memory/references/tool-reference.md +0 -90
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Export Training Data Command — Phase 1A (SLM Upgrade)
|
|
3
|
-
* Exports logged classification data as JSONL for model training.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* claude-brain export-training intent
|
|
7
|
-
* claude-brain export-training entity --verified-only
|
|
8
|
-
* claude-brain export-training compress --limit 500
|
|
9
|
-
* claude-brain export-training --stats
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { parseArgs } from 'citty'
|
|
13
|
-
import { exportTrainingData, getTrainingStats, type TrainingTask } from '@/training/data-store'
|
|
14
|
-
|
|
15
|
-
const VALID_TASKS: TrainingTask[] = ['intent', 'entity', 'query', 'knowledge', 'compress', 'pattern']
|
|
16
|
-
|
|
17
|
-
export async function runExportTraining() {
|
|
18
|
-
const args = parseArgs(process.argv.slice(3), {
|
|
19
|
-
task: { type: 'positional', description: 'Task to export: intent, entity, query, knowledge, compress, pattern' },
|
|
20
|
-
verifiedOnly: { type: 'boolean', alias: ['verified-only'], description: 'Only export human-verified examples' },
|
|
21
|
-
limit: { type: 'string', description: 'Max examples to export' },
|
|
22
|
-
stats: { type: 'boolean', description: 'Show training data statistics' },
|
|
23
|
-
format: { type: 'string', default: 'jsonl', description: 'Output format: jsonl or csv' },
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
// Stats mode
|
|
27
|
-
if (args.stats) {
|
|
28
|
-
const stats = getTrainingStats()
|
|
29
|
-
console.log('Training Data Statistics:')
|
|
30
|
-
console.log('========================')
|
|
31
|
-
let grandTotal = 0
|
|
32
|
-
let grandVerified = 0
|
|
33
|
-
for (const [task, counts] of Object.entries(stats)) {
|
|
34
|
-
console.log(` ${task.padEnd(12)} ${String(counts.total).padStart(6)} total ${String(counts.verified).padStart(6)} verified`)
|
|
35
|
-
grandTotal += counts.total
|
|
36
|
-
grandVerified += counts.verified
|
|
37
|
-
}
|
|
38
|
-
console.log(' ' + '-'.repeat(40))
|
|
39
|
-
console.log(` ${'TOTAL'.padEnd(12)} ${String(grandTotal).padStart(6)} total ${String(grandVerified).padStart(6)} verified`)
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const task = args.task as TrainingTask
|
|
44
|
-
if (!task || !VALID_TASKS.includes(task)) {
|
|
45
|
-
console.error(`Error: task must be one of: ${VALID_TASKS.join(', ')}`)
|
|
46
|
-
console.error('Usage: claude-brain export-training <task> [--verified-only] [--limit N]')
|
|
47
|
-
console.error(' claude-brain export-training --stats')
|
|
48
|
-
process.exit(1)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const limit = args.limit ? parseInt(args.limit, 10) : undefined
|
|
52
|
-
const lines = exportTrainingData(task, {
|
|
53
|
-
verifiedOnly: args.verifiedOnly || false,
|
|
54
|
-
limit,
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
if (lines.length === 0) {
|
|
58
|
-
console.error(`No training data found for task "${task}".`)
|
|
59
|
-
console.error('Training data is collected automatically as Claude Brain processes requests.')
|
|
60
|
-
process.exit(0)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Output to stdout (pipe-friendly)
|
|
64
|
-
for (const line of lines) {
|
|
65
|
-
console.log(line)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Summary to stderr so it doesn't pollute piped output
|
|
69
|
-
console.error(`\nExported ${lines.length} examples for task "${task}"`)
|
|
70
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Export Training Data Command — Phase 1A (SLM Upgrade)
|
|
3
|
+
* Exports logged classification data as JSONL for model training.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* claude-brain export-training intent
|
|
7
|
+
* claude-brain export-training entity --verified-only
|
|
8
|
+
* claude-brain export-training compress --limit 500
|
|
9
|
+
* claude-brain export-training --stats
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { parseArgs } from 'citty'
|
|
13
|
+
import { exportTrainingData, getTrainingStats, type TrainingTask } from '@/training/data-store'
|
|
14
|
+
|
|
15
|
+
const VALID_TASKS: TrainingTask[] = ['intent', 'entity', 'query', 'knowledge', 'compress', 'pattern']
|
|
16
|
+
|
|
17
|
+
export async function runExportTraining() {
|
|
18
|
+
const args = parseArgs(process.argv.slice(3), {
|
|
19
|
+
task: { type: 'positional', description: 'Task to export: intent, entity, query, knowledge, compress, pattern' },
|
|
20
|
+
verifiedOnly: { type: 'boolean', alias: ['verified-only'], description: 'Only export human-verified examples' },
|
|
21
|
+
limit: { type: 'string', description: 'Max examples to export' },
|
|
22
|
+
stats: { type: 'boolean', description: 'Show training data statistics' },
|
|
23
|
+
format: { type: 'string', default: 'jsonl', description: 'Output format: jsonl or csv' },
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// Stats mode
|
|
27
|
+
if (args.stats) {
|
|
28
|
+
const stats = getTrainingStats()
|
|
29
|
+
console.log('Training Data Statistics:')
|
|
30
|
+
console.log('========================')
|
|
31
|
+
let grandTotal = 0
|
|
32
|
+
let grandVerified = 0
|
|
33
|
+
for (const [task, counts] of Object.entries(stats)) {
|
|
34
|
+
console.log(` ${task.padEnd(12)} ${String(counts.total).padStart(6)} total ${String(counts.verified).padStart(6)} verified`)
|
|
35
|
+
grandTotal += counts.total
|
|
36
|
+
grandVerified += counts.verified
|
|
37
|
+
}
|
|
38
|
+
console.log(' ' + '-'.repeat(40))
|
|
39
|
+
console.log(` ${'TOTAL'.padEnd(12)} ${String(grandTotal).padStart(6)} total ${String(grandVerified).padStart(6)} verified`)
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const task = args.task as TrainingTask
|
|
44
|
+
if (!task || !VALID_TASKS.includes(task)) {
|
|
45
|
+
console.error(`Error: task must be one of: ${VALID_TASKS.join(', ')}`)
|
|
46
|
+
console.error('Usage: claude-brain export-training <task> [--verified-only] [--limit N]')
|
|
47
|
+
console.error(' claude-brain export-training --stats')
|
|
48
|
+
process.exit(1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const limit = args.limit ? parseInt(args.limit, 10) : undefined
|
|
52
|
+
const lines = exportTrainingData(task, {
|
|
53
|
+
verifiedOnly: args.verifiedOnly || false,
|
|
54
|
+
limit,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
if (lines.length === 0) {
|
|
58
|
+
console.error(`No training data found for task "${task}".`)
|
|
59
|
+
console.error('Training data is collected automatically as Claude Brain processes requests.')
|
|
60
|
+
process.exit(0)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Output to stdout (pipe-friendly)
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
console.log(line)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Summary to stderr so it doesn't pollute piped output
|
|
69
|
+
console.error(`\nExported ${lines.length} examples for task "${task}"`)
|
|
70
|
+
}
|
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Export Command — Phase 30
|
|
3
|
-
* Export observations for a project in markdown or JSON format.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* claude-brain export --project expense-tracker --format md > decisions.md
|
|
7
|
-
* claude-brain export --project expense-tracker --format json > decisions.json
|
|
8
|
-
* claude-brain export --project expense-tracker --category decision
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { join } from 'node:path'
|
|
12
|
-
import { existsSync } from 'node:fs'
|
|
13
|
-
import { parseArgs } from 'citty'
|
|
14
|
-
import { getClaudeBrainHome } from '@/config/home'
|
|
15
|
-
|
|
16
|
-
export async function runExport() {
|
|
17
|
-
const args = parseArgs(process.argv.slice(3), {
|
|
18
|
-
project: { type: 'string', description: 'Project name to export' },
|
|
19
|
-
format: { type: 'string', default: 'md', description: 'Output format: md or json' },
|
|
20
|
-
category: { type: 'string', description: 'Filter by category: decision, pattern, correction' },
|
|
21
|
-
limit: { type: 'string', default: '1000', description: 'Max observations to export' },
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const project = args.project
|
|
25
|
-
const format = args.format || 'md'
|
|
26
|
-
const category = args.category
|
|
27
|
-
const limit = parseInt(args.limit || '1000', 10)
|
|
28
|
-
|
|
29
|
-
if (!project) {
|
|
30
|
-
console.error('Error: --project is required')
|
|
31
|
-
console.error('Usage: claude-brain export --project <name> [--format md|json] [--category decision|pattern|correction]')
|
|
32
|
-
process.exit(1)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const dbPath = join(getClaudeBrainHome(), 'data', 'memory.db')
|
|
36
|
-
if (!existsSync(dbPath)) {
|
|
37
|
-
console.error('Error: No database found. Run claude-brain first to initialize.')
|
|
38
|
-
process.exit(1)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const { Database } = await import('bun:sqlite')
|
|
42
|
-
const db = new Database(dbPath, { readonly: true })
|
|
43
|
-
|
|
44
|
-
let sql = 'SELECT * FROM observations WHERE project = ? AND archived = 0'
|
|
45
|
-
const params:
|
|
46
|
-
|
|
47
|
-
if (category) {
|
|
48
|
-
sql += ' AND category = ?'
|
|
49
|
-
params.push(category)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
sql += ' ORDER BY created_at DESC LIMIT ?'
|
|
53
|
-
params.push(limit)
|
|
54
|
-
|
|
55
|
-
const rows = db.prepare(sql).all(...params) as
|
|
56
|
-
db.close()
|
|
57
|
-
|
|
58
|
-
if (rows.length === 0) {
|
|
59
|
-
console.error(`No observations found for project "${project}"${category ? ` with category "${category}"` : ''}.`)
|
|
60
|
-
process.exit(0)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (format === 'json') {
|
|
64
|
-
const output = rows.map(row => ({
|
|
65
|
-
id: row.id,
|
|
66
|
-
project: row.project,
|
|
67
|
-
category: row.category,
|
|
68
|
-
content: row.content,
|
|
69
|
-
reasoning: row.reasoning || null,
|
|
70
|
-
context: row.context || null,
|
|
71
|
-
confidence: row.confidence,
|
|
72
|
-
source: row.source,
|
|
73
|
-
tags: parseTags(row.tags),
|
|
74
|
-
created_at: row.created_at,
|
|
75
|
-
updated_at: row.updated_at,
|
|
76
|
-
}))
|
|
77
|
-
console.log(JSON.stringify(output, null, 2))
|
|
78
|
-
} else {
|
|
79
|
-
// Markdown format
|
|
80
|
-
const lines: string[] = []
|
|
81
|
-
lines.push(`# ${project} — Observations Export`)
|
|
82
|
-
lines.push('')
|
|
83
|
-
lines.push(`> Exported ${rows.length} observation(s) on ${new Date().toISOString().split('T')[0]}`)
|
|
84
|
-
lines.push('')
|
|
85
|
-
|
|
86
|
-
// Group by category
|
|
87
|
-
const grouped: Record<string,
|
|
88
|
-
for (const row of rows) {
|
|
89
|
-
const cat = row.category || 'other'
|
|
90
|
-
if (!grouped[cat]) grouped[cat] = []
|
|
91
|
-
grouped[cat].push(row)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
for (const [cat, items] of Object.entries(grouped)) {
|
|
95
|
-
lines.push(`## ${capitalize(cat)}s (${items.length})`)
|
|
96
|
-
lines.push('')
|
|
97
|
-
|
|
98
|
-
for (const item of items) {
|
|
99
|
-
const date = item.created_at ? item.created_at.split('T')[0] : 'unknown'
|
|
100
|
-
lines.push(`### ${(item.content as string).slice(0, 80)}`)
|
|
101
|
-
lines.push('')
|
|
102
|
-
lines.push(`- **Date:** ${date}`)
|
|
103
|
-
lines.push(`- **Content:** ${item.content}`)
|
|
104
|
-
if (item.reasoning) lines.push(`- **Reasoning:** ${item.reasoning}`)
|
|
105
|
-
if (item.context) lines.push(`- **Context:** ${item.context}`)
|
|
106
|
-
const tags = parseTags(item.tags)
|
|
107
|
-
if (tags.length > 0) lines.push(`- **Tags:** ${tags.join(', ')}`)
|
|
108
|
-
lines.push('')
|
|
109
|
-
lines.push('---')
|
|
110
|
-
lines.push('')
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.log(lines.join('\n'))
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function parseTags(value: string | null): string[] {
|
|
119
|
-
if (!value) return []
|
|
120
|
-
try {
|
|
121
|
-
const parsed = JSON.parse(value)
|
|
122
|
-
return Array.isArray(parsed) ? parsed : []
|
|
123
|
-
} catch {
|
|
124
|
-
return value.split(',').map(s => s.trim()).filter(Boolean)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function capitalize(s: string): string {
|
|
129
|
-
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
130
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Export Command — Phase 30
|
|
3
|
+
* Export observations for a project in markdown or JSON format.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* claude-brain export --project expense-tracker --format md > decisions.md
|
|
7
|
+
* claude-brain export --project expense-tracker --format json > decisions.json
|
|
8
|
+
* claude-brain export --project expense-tracker --category decision
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { join } from 'node:path'
|
|
12
|
+
import { existsSync } from 'node:fs'
|
|
13
|
+
import { parseArgs } from 'citty'
|
|
14
|
+
import { getClaudeBrainHome } from '@/config/home'
|
|
15
|
+
|
|
16
|
+
export async function runExport() {
|
|
17
|
+
const args = parseArgs(process.argv.slice(3), {
|
|
18
|
+
project: { type: 'string', description: 'Project name to export' },
|
|
19
|
+
format: { type: 'string', default: 'md', description: 'Output format: md or json' },
|
|
20
|
+
category: { type: 'string', description: 'Filter by category: decision, pattern, correction' },
|
|
21
|
+
limit: { type: 'string', default: '1000', description: 'Max observations to export' },
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const project = args.project
|
|
25
|
+
const format = args.format || 'md'
|
|
26
|
+
const category = args.category
|
|
27
|
+
const limit = parseInt(args.limit || '1000', 10)
|
|
28
|
+
|
|
29
|
+
if (!project) {
|
|
30
|
+
console.error('Error: --project is required')
|
|
31
|
+
console.error('Usage: claude-brain export --project <name> [--format md|json] [--category decision|pattern|correction]')
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const dbPath = join(getClaudeBrainHome(), 'data', 'memory.db')
|
|
36
|
+
if (!existsSync(dbPath)) {
|
|
37
|
+
console.error('Error: No database found. Run claude-brain first to initialize.')
|
|
38
|
+
process.exit(1)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { Database } = await import('bun:sqlite')
|
|
42
|
+
const db = new Database(dbPath, { readonly: true })
|
|
43
|
+
|
|
44
|
+
let sql = 'SELECT * FROM observations WHERE project = ? AND archived = 0'
|
|
45
|
+
const params: (string | number)[] = [project]
|
|
46
|
+
|
|
47
|
+
if (category) {
|
|
48
|
+
sql += ' AND category = ?'
|
|
49
|
+
params.push(category)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
sql += ' ORDER BY created_at DESC LIMIT ?'
|
|
53
|
+
params.push(limit)
|
|
54
|
+
|
|
55
|
+
const rows = db.prepare(sql).all(...params) as Record<string, unknown>[]
|
|
56
|
+
db.close()
|
|
57
|
+
|
|
58
|
+
if (rows.length === 0) {
|
|
59
|
+
console.error(`No observations found for project "${project}"${category ? ` with category "${category}"` : ''}.`)
|
|
60
|
+
process.exit(0)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (format === 'json') {
|
|
64
|
+
const output = rows.map(row => ({
|
|
65
|
+
id: row.id,
|
|
66
|
+
project: row.project,
|
|
67
|
+
category: row.category,
|
|
68
|
+
content: row.content,
|
|
69
|
+
reasoning: row.reasoning || null,
|
|
70
|
+
context: row.context || null,
|
|
71
|
+
confidence: row.confidence,
|
|
72
|
+
source: row.source,
|
|
73
|
+
tags: parseTags(row.tags),
|
|
74
|
+
created_at: row.created_at,
|
|
75
|
+
updated_at: row.updated_at,
|
|
76
|
+
}))
|
|
77
|
+
console.log(JSON.stringify(output, null, 2))
|
|
78
|
+
} else {
|
|
79
|
+
// Markdown format
|
|
80
|
+
const lines: string[] = []
|
|
81
|
+
lines.push(`# ${project} — Observations Export`)
|
|
82
|
+
lines.push('')
|
|
83
|
+
lines.push(`> Exported ${rows.length} observation(s) on ${new Date().toISOString().split('T')[0]}`)
|
|
84
|
+
lines.push('')
|
|
85
|
+
|
|
86
|
+
// Group by category
|
|
87
|
+
const grouped: Record<string, Record<string, unknown>[]> = {}
|
|
88
|
+
for (const row of rows) {
|
|
89
|
+
const cat = row.category || 'other'
|
|
90
|
+
if (!grouped[cat]) grouped[cat] = []
|
|
91
|
+
grouped[cat].push(row)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const [cat, items] of Object.entries(grouped)) {
|
|
95
|
+
lines.push(`## ${capitalize(cat)}s (${items.length})`)
|
|
96
|
+
lines.push('')
|
|
97
|
+
|
|
98
|
+
for (const item of items) {
|
|
99
|
+
const date = item.created_at ? item.created_at.split('T')[0] : 'unknown'
|
|
100
|
+
lines.push(`### ${(item.content as string).slice(0, 80)}`)
|
|
101
|
+
lines.push('')
|
|
102
|
+
lines.push(`- **Date:** ${date}`)
|
|
103
|
+
lines.push(`- **Content:** ${item.content}`)
|
|
104
|
+
if (item.reasoning) lines.push(`- **Reasoning:** ${item.reasoning}`)
|
|
105
|
+
if (item.context) lines.push(`- **Context:** ${item.context}`)
|
|
106
|
+
const tags = parseTags(item.tags)
|
|
107
|
+
if (tags.length > 0) lines.push(`- **Tags:** ${tags.join(', ')}`)
|
|
108
|
+
lines.push('')
|
|
109
|
+
lines.push('---')
|
|
110
|
+
lines.push('')
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(lines.join('\n'))
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function parseTags(value: string | null): string[] {
|
|
119
|
+
if (!value) return []
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(value)
|
|
122
|
+
return Array.isArray(parsed) ? parsed : []
|
|
123
|
+
} catch {
|
|
124
|
+
return value.split(',').map(s => s.trim()).filter(Boolean)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function capitalize(s: string): string {
|
|
129
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
130
|
+
}
|