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
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory / brain routes
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Hono } from 'hono'
|
|
6
|
+
import type { Context } from 'hono'
|
|
7
|
+
import { isServicesInitialized, getMemoryService, getVaultService } from '@/server/services'
|
|
8
|
+
import { validateBody, validateQuery } from '@/server/middleware/validate'
|
|
9
|
+
import {
|
|
10
|
+
RecallQuerySchema,
|
|
11
|
+
RememberDecisionSchema,
|
|
12
|
+
RecognizePatternSchema,
|
|
13
|
+
RecordCorrectionSchema,
|
|
14
|
+
UpdateProgressSchema,
|
|
15
|
+
FileQuerySchema,
|
|
16
|
+
} from '@/server/schemas/api-schemas'
|
|
17
|
+
import { formatAge } from './helpers'
|
|
18
|
+
import type { RouteDeps } from './types'
|
|
19
|
+
|
|
20
|
+
export function registerMemoryRoutes(app: Hono, deps: RouteDeps): void {
|
|
21
|
+
app.get('/api/claude-brain/smart-context/:projectName', (c) => handleSmartContext(c, deps))
|
|
22
|
+
app.get('/api/claude-brain/project-context/:projectName', (c) => handleProjectContext(c, deps))
|
|
23
|
+
app.get('/api/claude-brain/recall-similar', (c) => handleRecallSimilar(c, deps))
|
|
24
|
+
app.get('/api/claude-brain/get-decisions', () => handleGetDecisions(deps))
|
|
25
|
+
app.get('/api/claude-brain/get-patterns', () => handleGetPatterns(deps))
|
|
26
|
+
app.get('/api/claude-brain/get-corrections', () => handleGetCorrections(deps))
|
|
27
|
+
app.post('/api/claude-brain/remember-decision', (c) => handleRememberDecision(c, deps))
|
|
28
|
+
app.post('/api/claude-brain/recognize-pattern', (c) => handleRecognizePattern(c, deps))
|
|
29
|
+
app.post('/api/claude-brain/record-correction', (c) => handleRecordCorrection(c, deps))
|
|
30
|
+
app.post('/api/claude-brain/update-progress', (c) => handleUpdateProgress(c, deps))
|
|
31
|
+
app.get('/api/memory/for-file', (c) => handleMemoryForFile(c, deps))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function handleSmartContext(c: Context, deps: RouteDeps): Promise<Response> {
|
|
35
|
+
try {
|
|
36
|
+
const projectName = c.req.param('projectName')
|
|
37
|
+
const vaultService = getVaultService()
|
|
38
|
+
|
|
39
|
+
if (!vaultService) {
|
|
40
|
+
return Response.json({ success: true, data: {} })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const context = await vaultService.getProjectContext(projectName)
|
|
44
|
+
|
|
45
|
+
return Response.json({
|
|
46
|
+
success: true,
|
|
47
|
+
data: {
|
|
48
|
+
description: context?.content || '',
|
|
49
|
+
tech_stack: [],
|
|
50
|
+
tags: [],
|
|
51
|
+
phase: 'setup',
|
|
52
|
+
completion: 0,
|
|
53
|
+
decisions: [],
|
|
54
|
+
patterns: [],
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
} catch (error) {
|
|
58
|
+
deps.logger.error({ error }, 'Failed to get smart context')
|
|
59
|
+
return Response.json(
|
|
60
|
+
{ success: false, error: 'Failed to get context' },
|
|
61
|
+
{ status: 500 }
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function handleProjectContext(c: Context, deps: RouteDeps): Promise<Response> {
|
|
67
|
+
try {
|
|
68
|
+
const projectName = c.req.param('projectName')
|
|
69
|
+
const vaultService = getVaultService()
|
|
70
|
+
|
|
71
|
+
if (!vaultService) {
|
|
72
|
+
return Response.json({ success: false, error: 'Vault service not available' }, { status: 500 })
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const metadata = await vaultService.getProjectMetadata(projectName)
|
|
76
|
+
|
|
77
|
+
if (!metadata) {
|
|
78
|
+
return Response.json({ success: false, error: 'Project not found' }, { status: 404 })
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return Response.json({
|
|
82
|
+
success: true,
|
|
83
|
+
data: {
|
|
84
|
+
project: {
|
|
85
|
+
id: projectName,
|
|
86
|
+
name: projectName,
|
|
87
|
+
techStack: metadata.techStack,
|
|
88
|
+
status: metadata.status,
|
|
89
|
+
tags: metadata.tags,
|
|
90
|
+
},
|
|
91
|
+
progress: {
|
|
92
|
+
phase: metadata.currentPhase || 'setup',
|
|
93
|
+
completion: metadata.completionPercentage || 0,
|
|
94
|
+
completed_task: '',
|
|
95
|
+
next_steps: '',
|
|
96
|
+
notes: '',
|
|
97
|
+
},
|
|
98
|
+
decisions: [],
|
|
99
|
+
patterns: [],
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
} catch (error) {
|
|
103
|
+
deps.logger.error({ error }, 'Failed to get project context')
|
|
104
|
+
return Response.json(
|
|
105
|
+
{ success: false, error: 'Failed to get project context' },
|
|
106
|
+
{ status: 500 }
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function handleRecallSimilar(c: Context, deps: RouteDeps): Promise<Response> {
|
|
112
|
+
try {
|
|
113
|
+
const params = validateQuery(c, RecallQuerySchema)
|
|
114
|
+
const query = params?.query ?? ''
|
|
115
|
+
|
|
116
|
+
const memoryService = getMemoryService()
|
|
117
|
+
|
|
118
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
119
|
+
return Response.json({ success: true, data: [] })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const resultText = await memoryService.recallSimilar(query, {
|
|
123
|
+
limit: 10,
|
|
124
|
+
minSimilarity: 0.3,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const memories = resultText ? [{
|
|
128
|
+
id: 'recall-result',
|
|
129
|
+
type: 'memory',
|
|
130
|
+
title: query,
|
|
131
|
+
description: resultText,
|
|
132
|
+
timestamp: new Date().toISOString(),
|
|
133
|
+
project: '',
|
|
134
|
+
tags: [] as string[],
|
|
135
|
+
context: resultText,
|
|
136
|
+
similarity: 0.8,
|
|
137
|
+
}] : []
|
|
138
|
+
|
|
139
|
+
return Response.json({ success: true, data: memories })
|
|
140
|
+
} catch (error) {
|
|
141
|
+
deps.logger.error({ error }, 'Failed to recall similar memories')
|
|
142
|
+
return Response.json(
|
|
143
|
+
{ success: false, error: 'Failed to search memories' },
|
|
144
|
+
{ status: 500 }
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function handleGetDecisions(deps: RouteDeps): Promise<Response> {
|
|
150
|
+
try {
|
|
151
|
+
const memoryService = getMemoryService()
|
|
152
|
+
|
|
153
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
154
|
+
return Response.json({ success: true, data: [] })
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const decisions = await memoryService.fetchAllDecisions()
|
|
158
|
+
|
|
159
|
+
return Response.json({ success: true, data: decisions })
|
|
160
|
+
} catch (error) {
|
|
161
|
+
deps.logger.error({ error }, 'Failed to get decisions')
|
|
162
|
+
return Response.json(
|
|
163
|
+
{ success: false, error: 'Failed to get decisions' },
|
|
164
|
+
{ status: 500 }
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function handleGetPatterns(deps: RouteDeps): Promise<Response> {
|
|
170
|
+
try {
|
|
171
|
+
const memoryService = getMemoryService()
|
|
172
|
+
|
|
173
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
174
|
+
return Response.json({ success: true, data: [] })
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const patterns = await memoryService.getPatterns(undefined, { limit: 100 })
|
|
178
|
+
|
|
179
|
+
return Response.json({ success: true, data: patterns })
|
|
180
|
+
} catch (error) {
|
|
181
|
+
deps.logger.error({ error }, 'Failed to get patterns')
|
|
182
|
+
return Response.json(
|
|
183
|
+
{ success: false, error: 'Failed to get patterns' },
|
|
184
|
+
{ status: 500 }
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function handleGetCorrections(deps: RouteDeps): Promise<Response> {
|
|
190
|
+
try {
|
|
191
|
+
const memoryService = getMemoryService()
|
|
192
|
+
|
|
193
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
194
|
+
return Response.json({ success: true, data: [] })
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const corrections = await memoryService.getCorrections(undefined, { limit: 100 })
|
|
198
|
+
|
|
199
|
+
return Response.json({ success: true, data: corrections })
|
|
200
|
+
} catch (error) {
|
|
201
|
+
deps.logger.error({ error }, 'Failed to get corrections')
|
|
202
|
+
return Response.json(
|
|
203
|
+
{ success: false, error: 'Failed to get corrections' },
|
|
204
|
+
{ status: 500 }
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function handleRememberDecision(c: Context, deps: RouteDeps): Promise<Response> {
|
|
210
|
+
try {
|
|
211
|
+
const data = await validateBody(c, RememberDecisionSchema)
|
|
212
|
+
if (!data) return Response.json({ success: false, error: 'Validation failed' }, { status: 400 })
|
|
213
|
+
|
|
214
|
+
const memoryService = getMemoryService()
|
|
215
|
+
|
|
216
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
217
|
+
throw new Error('Memory service not initialized')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
await memoryService.rememberDecision(
|
|
221
|
+
data.project_name,
|
|
222
|
+
data.context || '',
|
|
223
|
+
data.decision,
|
|
224
|
+
data.reasoning || '',
|
|
225
|
+
{ tags: data.tags }
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
return Response.json({ success: true, data: { message: 'Decision stored successfully' } })
|
|
229
|
+
} catch (error) {
|
|
230
|
+
deps.logger.error({ error }, 'Failed to remember decision')
|
|
231
|
+
return Response.json(
|
|
232
|
+
{ success: false, error: 'Failed to store decision' },
|
|
233
|
+
{ status: 500 }
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function handleRecognizePattern(c: Context, deps: RouteDeps): Promise<Response> {
|
|
239
|
+
try {
|
|
240
|
+
const data = await validateBody(c, RecognizePatternSchema)
|
|
241
|
+
if (!data) return Response.json({ success: false, error: 'Validation failed' }, { status: 400 })
|
|
242
|
+
|
|
243
|
+
const memoryService = getMemoryService()
|
|
244
|
+
|
|
245
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
246
|
+
throw new Error('Memory service not initialized')
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
await memoryService.storePattern({
|
|
250
|
+
description: data.description,
|
|
251
|
+
pattern_type: data.pattern_type,
|
|
252
|
+
context: data.context,
|
|
253
|
+
example: data.example,
|
|
254
|
+
project: data.project_name,
|
|
255
|
+
confidence: data.confidence,
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
return Response.json({ success: true, data: { message: 'Pattern stored successfully' } })
|
|
259
|
+
} catch (error) {
|
|
260
|
+
deps.logger.error({ error }, 'Failed to recognize pattern')
|
|
261
|
+
return Response.json(
|
|
262
|
+
{ success: false, error: 'Failed to store pattern' },
|
|
263
|
+
{ status: 500 }
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function handleRecordCorrection(c: Context, deps: RouteDeps): Promise<Response> {
|
|
269
|
+
try {
|
|
270
|
+
const data = await validateBody(c, RecordCorrectionSchema)
|
|
271
|
+
if (!data) return Response.json({ success: false, error: 'Validation failed' }, { status: 400 })
|
|
272
|
+
|
|
273
|
+
const memoryService = getMemoryService()
|
|
274
|
+
|
|
275
|
+
if (!memoryService || !memoryService.isInitialized()) {
|
|
276
|
+
throw new Error('Memory service not initialized')
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
await memoryService.storeCorrection({
|
|
280
|
+
original: data.original,
|
|
281
|
+
correction: data.correction,
|
|
282
|
+
reasoning: data.reasoning,
|
|
283
|
+
context: data.context,
|
|
284
|
+
project: data.project_name,
|
|
285
|
+
confidence: data.confidence,
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
return Response.json({ success: true, data: { message: 'Correction stored successfully' } })
|
|
289
|
+
} catch (error) {
|
|
290
|
+
deps.logger.error({ error }, 'Failed to record correction')
|
|
291
|
+
return Response.json(
|
|
292
|
+
{ success: false, error: 'Failed to store correction' },
|
|
293
|
+
{ status: 500 }
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
async function handleUpdateProgress(c: Context, deps: RouteDeps): Promise<Response> {
|
|
299
|
+
try {
|
|
300
|
+
const data = await validateBody(c, UpdateProgressSchema)
|
|
301
|
+
if (!data) return Response.json({ success: false, error: 'Validation failed' }, { status: 400 })
|
|
302
|
+
|
|
303
|
+
const vaultService = getVaultService()
|
|
304
|
+
|
|
305
|
+
if (!vaultService) {
|
|
306
|
+
throw new Error('Vault service not initialized')
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const updates: Record<string, string> = {}
|
|
310
|
+
if (data.completed_task) {
|
|
311
|
+
updates.status = `Completed: ${data.completed_task}`
|
|
312
|
+
}
|
|
313
|
+
if (data.next_steps) updates.next_steps = data.next_steps
|
|
314
|
+
if (data.notes) updates.notes = data.notes
|
|
315
|
+
|
|
316
|
+
await vaultService.updateProgress(data.project_name, updates)
|
|
317
|
+
|
|
318
|
+
return Response.json({ success: true, data: { message: 'Progress updated successfully' } })
|
|
319
|
+
} catch (error) {
|
|
320
|
+
deps.logger.error({ error }, 'Failed to update progress')
|
|
321
|
+
return Response.json(
|
|
322
|
+
{ success: false, error: 'Failed to update progress' },
|
|
323
|
+
{ status: 500 }
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function handleMemoryForFile(c: Context, deps: RouteDeps): Response {
|
|
329
|
+
try {
|
|
330
|
+
const params = validateQuery(c, FileQuerySchema)
|
|
331
|
+
if (!params) {
|
|
332
|
+
return Response.json(
|
|
333
|
+
{ success: false, error: 'Validation failed: file query parameter is required' },
|
|
334
|
+
{ status: 400 }
|
|
335
|
+
)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const file = params.file
|
|
339
|
+
const project = params.project || ''
|
|
340
|
+
|
|
341
|
+
if (!isServicesInitialized()) {
|
|
342
|
+
return Response.json({ success: true, data: { file, memoryCount: 0, summary: '' } })
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const memoryService = getMemoryService()
|
|
346
|
+
if (!memoryService?.fts5) {
|
|
347
|
+
return Response.json({ success: true, data: { file, memoryCount: 0, summary: '' } })
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const db = memoryService.database.getDb()
|
|
351
|
+
const likePattern = `%${file}%`
|
|
352
|
+
|
|
353
|
+
interface FileMemoryRow { id: string; category: string; content: string; reasoning: string; created_at: string }
|
|
354
|
+
let rows: FileMemoryRow[]
|
|
355
|
+
if (project) {
|
|
356
|
+
rows = db.prepare(`
|
|
357
|
+
SELECT id, category, content, reasoning, created_at
|
|
358
|
+
FROM observations
|
|
359
|
+
WHERE project = ? AND file_paths LIKE ? AND archived = 0
|
|
360
|
+
ORDER BY created_at DESC
|
|
361
|
+
LIMIT 5
|
|
362
|
+
`).all(project, likePattern) as FileMemoryRow[]
|
|
363
|
+
} else {
|
|
364
|
+
rows = db.prepare(`
|
|
365
|
+
SELECT id, category, content, reasoning, created_at
|
|
366
|
+
FROM observations
|
|
367
|
+
WHERE file_paths LIKE ? AND archived = 0
|
|
368
|
+
ORDER BY created_at DESC
|
|
369
|
+
LIMIT 5
|
|
370
|
+
`).all(likePattern) as FileMemoryRow[]
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (rows.length === 0) {
|
|
374
|
+
return Response.json({ success: true, data: { file, memoryCount: 0, summary: '' } })
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const lines = rows.map((r: FileMemoryRow) => {
|
|
378
|
+
const age = formatAge(r.created_at)
|
|
379
|
+
return `- [${r.category}] ${(r.content as string).slice(0, 120)} (${age})`
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
return Response.json({
|
|
383
|
+
success: true,
|
|
384
|
+
data: {
|
|
385
|
+
file,
|
|
386
|
+
memoryCount: rows.length,
|
|
387
|
+
summary: `Memories linked to ${file}:\n${lines.join('\n')}`
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
} catch (error) {
|
|
391
|
+
deps.logger.error({ error }, 'Failed to get memories for file')
|
|
392
|
+
return Response.json(
|
|
393
|
+
{ success: false, error: 'Failed to get memories for file' },
|
|
394
|
+
{ status: 500 }
|
|
395
|
+
)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SLM model and training routes
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Hono } from 'hono'
|
|
6
|
+
import type { Context } from 'hono'
|
|
7
|
+
import { getInferenceRouter } from '@/server/services'
|
|
8
|
+
import { getTrainingStats, getModelFeedbackStats, getDisagreements } from '@/training/data-store'
|
|
9
|
+
import { validateQuery } from '@/server/middleware/validate'
|
|
10
|
+
import {
|
|
11
|
+
ModelsFeedbackQuerySchema,
|
|
12
|
+
ModelsDisagreementsQuerySchema,
|
|
13
|
+
} from '@/server/schemas/api-schemas'
|
|
14
|
+
import type { RouteDeps } from './types'
|
|
15
|
+
|
|
16
|
+
export function registerModelRoutes(app: Hono, deps: RouteDeps): void {
|
|
17
|
+
app.get('/api/models/status', () => handleModelsStatus(deps))
|
|
18
|
+
app.get('/api/models/feedback', (c) => handleModelsFeedback(c, deps))
|
|
19
|
+
app.get('/api/models/disagreements', (c) => handleModelsDisagreements(c, deps))
|
|
20
|
+
app.get('/api/training/stats', () => handleTrainingStats(deps))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function handleModelsStatus(deps: RouteDeps): Response {
|
|
24
|
+
try {
|
|
25
|
+
const inferenceRouter = getInferenceRouter()
|
|
26
|
+
if (!inferenceRouter) {
|
|
27
|
+
return Response.json({
|
|
28
|
+
success: true,
|
|
29
|
+
data: { enabled: false, message: 'SLM inference not initialized' },
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
return Response.json({ success: true, data: inferenceRouter.getStatus() })
|
|
33
|
+
} catch (error) {
|
|
34
|
+
deps.logger.error({ error }, 'Failed to get model status')
|
|
35
|
+
return Response.json(
|
|
36
|
+
{ success: false, error: 'Failed to get model status' },
|
|
37
|
+
{ status: 500 }
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function handleModelsFeedback(c: Context, deps: RouteDeps): Response {
|
|
43
|
+
try {
|
|
44
|
+
const params = validateQuery(c, ModelsFeedbackQuerySchema)
|
|
45
|
+
const task = params?.task
|
|
46
|
+
const stats = getModelFeedbackStats()
|
|
47
|
+
|
|
48
|
+
if (task) {
|
|
49
|
+
const taskStats = stats[task]
|
|
50
|
+
if (!taskStats) {
|
|
51
|
+
return Response.json(
|
|
52
|
+
{ success: false, error: `Unknown task: ${task}` },
|
|
53
|
+
{ status: 400 }
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
return Response.json({ success: true, data: { [task]: taskStats } })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return Response.json({ success: true, data: stats })
|
|
60
|
+
} catch (error) {
|
|
61
|
+
deps.logger.error({ error }, 'Failed to get model feedback stats')
|
|
62
|
+
return Response.json(
|
|
63
|
+
{ success: false, error: 'Failed to get model feedback stats' },
|
|
64
|
+
{ status: 500 }
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleModelsDisagreements(c: Context, deps: RouteDeps): Response {
|
|
70
|
+
try {
|
|
71
|
+
const params = validateQuery(c, ModelsDisagreementsQuerySchema)
|
|
72
|
+
const task = params?.task ?? 'intent'
|
|
73
|
+
const limit = params?.limit ?? 50
|
|
74
|
+
const disagreements = getDisagreements(task, limit)
|
|
75
|
+
return Response.json({ success: true, data: disagreements })
|
|
76
|
+
} catch (error) {
|
|
77
|
+
deps.logger.error({ error }, 'Failed to get model disagreements')
|
|
78
|
+
return Response.json(
|
|
79
|
+
{ success: false, error: 'Failed to get model disagreements' },
|
|
80
|
+
{ status: 500 }
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function handleTrainingStats(deps: RouteDeps): Response {
|
|
86
|
+
try {
|
|
87
|
+
const stats = getTrainingStats()
|
|
88
|
+
return Response.json({ success: true, data: stats })
|
|
89
|
+
} catch (error) {
|
|
90
|
+
deps.logger.error({ error }, 'Failed to get training stats')
|
|
91
|
+
return Response.json(
|
|
92
|
+
{ success: false, error: 'Failed to get training stats' },
|
|
93
|
+
{ status: 500 }
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project routes
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Hono } from 'hono'
|
|
6
|
+
import type { Context } from 'hono'
|
|
7
|
+
import { isServicesInitialized, getVaultService } from '@/server/services'
|
|
8
|
+
import { validateBody } from '@/server/middleware/validate'
|
|
9
|
+
import { CreateProjectSchema } from '@/server/schemas/api-schemas'
|
|
10
|
+
import type { RouteDeps } from './types'
|
|
11
|
+
|
|
12
|
+
export function registerProjectRoutes(app: Hono, deps: RouteDeps): void {
|
|
13
|
+
app.get('/api/projects/list', () => handleListProjects(deps))
|
|
14
|
+
app.post('/api/projects/create', (c) => handleCreateProject(c, deps))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function handleListProjects(deps: RouteDeps): Promise<Response> {
|
|
18
|
+
try {
|
|
19
|
+
if (!isServicesInitialized()) {
|
|
20
|
+
return Response.json({ success: true, data: [] })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const vaultService = getVaultService()
|
|
24
|
+
if (!vaultService) {
|
|
25
|
+
return Response.json({ success: true, data: [] })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const projectNames = await vaultService.listProjects()
|
|
29
|
+
|
|
30
|
+
const projects = []
|
|
31
|
+
for (const name of projectNames) {
|
|
32
|
+
try {
|
|
33
|
+
const metadata = await vaultService.getProjectMetadata(name)
|
|
34
|
+
projects.push({
|
|
35
|
+
id: name,
|
|
36
|
+
name,
|
|
37
|
+
techStack: metadata?.techStack || [],
|
|
38
|
+
status: metadata?.status || 'active',
|
|
39
|
+
tags: metadata?.tags || [],
|
|
40
|
+
createdAt: new Date().toISOString(),
|
|
41
|
+
})
|
|
42
|
+
} catch (error) {
|
|
43
|
+
// Skip projects that fail to load
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return Response.json({ success: true, data: projects })
|
|
48
|
+
} catch (error) {
|
|
49
|
+
deps.logger.error({ error }, 'Failed to list projects')
|
|
50
|
+
return Response.json(
|
|
51
|
+
{ success: false, error: 'Failed to list projects' },
|
|
52
|
+
{ status: 500 }
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function handleCreateProject(c: Context, deps: RouteDeps): Promise<Response> {
|
|
58
|
+
try {
|
|
59
|
+
const data = await validateBody(c, CreateProjectSchema)
|
|
60
|
+
if (!data) return Response.json({ success: false, error: 'Validation failed' }, { status: 400 })
|
|
61
|
+
|
|
62
|
+
const vaultService = getVaultService()
|
|
63
|
+
|
|
64
|
+
if (!vaultService) {
|
|
65
|
+
throw new Error('Vault service not initialized')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const normalizedName = data.name.replace(/\s+/g, '-').toLowerCase()
|
|
69
|
+
await vaultService.createProject(normalizedName)
|
|
70
|
+
|
|
71
|
+
const project = {
|
|
72
|
+
id: normalizedName,
|
|
73
|
+
name: normalizedName,
|
|
74
|
+
description: data.description || '',
|
|
75
|
+
techStack: data.techStack || [],
|
|
76
|
+
status: data.status || 'planning',
|
|
77
|
+
tags: data.tags || [],
|
|
78
|
+
createdAt: new Date().toISOString(),
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return Response.json({ success: true, data: project })
|
|
82
|
+
} catch (error) {
|
|
83
|
+
deps.logger.error({ error }, 'Failed to create project')
|
|
84
|
+
return Response.json(
|
|
85
|
+
{ success: false, error: 'Failed to create project' },
|
|
86
|
+
{ status: 500 }
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for route modules
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Logger } from 'pino'
|
|
6
|
+
import type { Config } from '@/config'
|
|
7
|
+
import type { HookSessionTracker } from '@/hooks/session-tracker'
|
|
8
|
+
import type { CodeIndexer } from '@/code-intelligence/indexer'
|
|
9
|
+
import type { CodeQuery } from '@/code-intelligence/query'
|
|
10
|
+
import type { MemoryCodeLinker } from '@/code-intelligence/linker'
|
|
11
|
+
import type { HookStats } from '@/hooks/types'
|
|
12
|
+
|
|
13
|
+
export interface RouteDeps {
|
|
14
|
+
logger: Logger
|
|
15
|
+
config: Config
|
|
16
|
+
getSessionTracker: () => HookSessionTracker | undefined
|
|
17
|
+
getCodeIndexer: () => CodeIndexer | undefined
|
|
18
|
+
getCodeQuery: () => CodeQuery | undefined
|
|
19
|
+
getCodeLinker: () => MemoryCodeLinker | undefined
|
|
20
|
+
hookStats: HookStats
|
|
21
|
+
}
|