claude-brain 0.14.2 → 0.14.4
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 +191 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +11 -11
- package/bunfig.toml +8 -8
- package/package.json +80 -80
- 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/src/automation/auto-context.ts +240 -240
- package/src/automation/decision-detector.ts +452 -452
- package/src/automation/index.ts +11 -11
- 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 +205 -205
- package/src/cli/auto-setup.ts +82 -82
- package/src/cli/bin.ts +202 -202
- package/src/cli/commands/chroma.ts +573 -573
- package/src/cli/commands/git-hook.ts +189 -189
- package/src/cli/commands/hooks.ts +213 -213
- package/src/cli/commands/init.ts +122 -122
- package/src/cli/commands/install-mcp.ts +92 -92
- package/src/cli/commands/pack.ts +197 -197
- package/src/cli/commands/serve.ts +167 -167
- package/src/cli/commands/start.ts +42 -42
- package/src/cli/commands/uninstall-mcp.ts +41 -41
- package/src/cli/commands/update.ts +121 -121
- package/src/cli/diagnose.ts +4 -4
- package/src/cli/health-check.ts +4 -4
- package/src/cli/migrate-chroma.ts +106 -106
- package/src/cli/setup.ts +4 -4
- 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/config/defaults.ts +50 -50
- package/src/config/home.ts +55 -55
- package/src/config/index.ts +7 -7
- package/src/config/loader.ts +166 -166
- package/src/config/migration.ts +76 -76
- package/src/config/schema.ts +360 -360
- package/src/config/validator.ts +184 -184
- package/src/config/watcher.ts +86 -86
- package/src/context/assembler.ts +398 -398
- package/src/context/cache-manager.ts +101 -101
- package/src/context/formatter.ts +84 -84
- package/src/context/hierarchy.ts +85 -85
- package/src/context/index.ts +83 -83
- package/src/context/progress-tracker.ts +174 -174
- package/src/context/standards-manager.ts +287 -287
- package/src/context/types.ts +252 -252
- package/src/context/validator.ts +58 -58
- package/src/diagnostics/index.ts +123 -123
- package/src/health/index.ts +229 -229
- package/src/hooks/brain-hook.ts +112 -112
- package/src/hooks/capture.ts +168 -168
- package/src/hooks/deduplicator.ts +72 -72
- package/src/hooks/git-capture.ts +109 -109
- package/src/hooks/git-hook-installer.ts +207 -207
- package/src/hooks/index.ts +20 -20
- package/src/hooks/installer.ts +191 -194
- package/src/hooks/passive-classifier.ts +366 -366
- package/src/hooks/queue.ts +129 -129
- package/src/hooks/session-tracker.ts +275 -275
- package/src/hooks/types.ts +47 -47
- package/src/index.ts +7 -7
- package/src/intelligence/cross-project/affinity.ts +162 -162
- package/src/intelligence/cross-project/generalizer.ts +283 -283
- package/src/intelligence/cross-project/index.ts +13 -13
- package/src/intelligence/cross-project/transfer.ts +201 -201
- package/src/intelligence/index.ts +24 -24
- package/src/intelligence/optimization/index.ts +10 -10
- package/src/intelligence/optimization/precompute.ts +202 -202
- package/src/intelligence/optimization/semantic-cache.ts +207 -207
- package/src/intelligence/prediction/context-anticipator.ts +198 -198
- package/src/intelligence/prediction/decision-predictor.ts +184 -184
- package/src/intelligence/prediction/index.ts +13 -13
- package/src/intelligence/prediction/recommender.ts +268 -268
- package/src/intelligence/reasoning/chain-retrieval.ts +247 -247
- package/src/intelligence/reasoning/counterfactual.ts +248 -248
- package/src/intelligence/reasoning/index.ts +13 -13
- package/src/intelligence/reasoning/synthesizer.ts +169 -169
- package/src/intelligence/temporal/evolution.ts +197 -197
- package/src/intelligence/temporal/index.ts +16 -16
- package/src/intelligence/temporal/query-processor.ts +190 -190
- package/src/intelligence/temporal/timeline.ts +259 -259
- package/src/intelligence/temporal/trends.ts +263 -263
- package/src/knowledge/entity-extractor.ts +416 -416
- 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 +168 -168
- package/src/knowledge/relationship-extractor.ts +108 -108
- package/src/memory/chroma/client.ts +174 -174
- package/src/memory/chroma/collection-manager.ts +94 -94
- package/src/memory/chroma/config.ts +57 -57
- package/src/memory/chroma/embeddings.ts +153 -153
- 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 +315 -315
- package/src/memory/chroma/store.ts +741 -741
- package/src/memory/consolidation/archiver.ts +164 -164
- package/src/memory/consolidation/merger.ts +186 -186
- package/src/memory/consolidation/scorer.ts +138 -138
- package/src/memory/context-builder.ts +236 -236
- package/src/memory/database.ts +169 -169
- package/src/memory/embedding-utils.ts +156 -156
- package/src/memory/embeddings.ts +226 -226
- package/src/memory/episodic/detector.ts +108 -108
- package/src/memory/episodic/manager.ts +351 -351
- package/src/memory/episodic/summarizer.ts +179 -179
- package/src/memory/episodic/types.ts +52 -52
- package/src/memory/index.ts +582 -582
- package/src/memory/knowledge-extractor.ts +455 -455
- package/src/memory/learning.ts +378 -378
- package/src/memory/patterns.ts +396 -396
- package/src/memory/schema.ts +88 -88
- package/src/memory/search.ts +309 -309
- package/src/memory/store.ts +787 -787
- package/src/memory/types.ts +121 -121
- package/src/orchestrator/coordinator.ts +272 -272
- package/src/orchestrator/decision-logger.ts +228 -228
- package/src/orchestrator/event-emitter.ts +198 -198
- package/src/orchestrator/event-queue.ts +184 -184
- package/src/orchestrator/handlers/base-handler.ts +70 -70
- package/src/orchestrator/handlers/context-handler.ts +73 -73
- package/src/orchestrator/handlers/decision-handler.ts +204 -204
- package/src/orchestrator/handlers/index.ts +10 -10
- package/src/orchestrator/handlers/status-handler.ts +131 -131
- package/src/orchestrator/handlers/task-handler.ts +171 -171
- package/src/orchestrator/index.ts +275 -275
- package/src/orchestrator/task-parser.ts +284 -284
- package/src/orchestrator/types.ts +98 -98
- 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 -300
- package/src/retrieval/bm25/tokenizer.ts +184 -184
- package/src/retrieval/feedback/adaptive.ts +223 -223
- package/src/retrieval/feedback/index.ts +16 -16
- package/src/retrieval/feedback/metrics.ts +223 -223
- package/src/retrieval/feedback/store.ts +283 -283
- package/src/retrieval/fusion/index.ts +194 -194
- package/src/retrieval/fusion/rrf.ts +163 -163
- package/src/retrieval/index.ts +12 -12
- package/src/retrieval/pipeline.ts +375 -375
- package/src/retrieval/query/expander.ts +198 -198
- package/src/retrieval/query/index.ts +27 -27
- package/src/retrieval/query/intent-classifier.ts +236 -236
- package/src/retrieval/query/temporal-parser.ts +295 -295
- package/src/retrieval/reranker/index.ts +188 -188
- package/src/retrieval/reranker/model.ts +95 -95
- package/src/retrieval/service.ts +125 -125
- package/src/retrieval/types.ts +162 -162
- package/src/routing/entity-extractor.ts +428 -428
- package/src/routing/intent-classifier.ts +436 -436
- package/src/routing/response-filter.ts +258 -254
- package/src/routing/router.ts +1322 -1314
- package/src/routing/search-engine.ts +475 -475
- package/src/routing/types.ts +94 -84
- package/src/scripts/health-check.ts +118 -118
- package/src/scripts/setup.ts +122 -122
- package/src/server/handlers/call-tool.ts +156 -156
- package/src/server/handlers/index.ts +9 -9
- package/src/server/handlers/list-tools.ts +35 -35
- package/src/server/handlers/tools/analyze-decision-evolution.ts +151 -151
- package/src/server/handlers/tools/auto-remember.ts +200 -200
- package/src/server/handlers/tools/brain.ts +85 -85
- package/src/server/handlers/tools/create-project.ts +135 -135
- package/src/server/handlers/tools/detect-trends.ts +144 -144
- package/src/server/handlers/tools/find-cross-project-patterns.ts +168 -168
- package/src/server/handlers/tools/get-activity-log.ts +194 -194
- package/src/server/handlers/tools/get-code-standards.ts +124 -124
- package/src/server/handlers/tools/get-corrections.ts +154 -154
- package/src/server/handlers/tools/get-decision-timeline.ts +172 -172
- package/src/server/handlers/tools/get-episode.ts +103 -103
- package/src/server/handlers/tools/get-patterns.ts +158 -158
- package/src/server/handlers/tools/get-phase12-status.ts +63 -63
- package/src/server/handlers/tools/get-project-context.ts +75 -75
- package/src/server/handlers/tools/get-recommendations.ts +145 -145
- package/src/server/handlers/tools/index.ts +31 -31
- package/src/server/handlers/tools/init-project.ts +757 -757
- package/src/server/handlers/tools/list-episodes.ts +90 -90
- package/src/server/handlers/tools/list-projects.ts +125 -125
- package/src/server/handlers/tools/rate-memory.ts +101 -101
- package/src/server/handlers/tools/recall-similar.ts +87 -87
- package/src/server/handlers/tools/recognize-pattern.ts +126 -126
- package/src/server/handlers/tools/record-correction.ts +125 -125
- package/src/server/handlers/tools/remember-decision.ts +153 -153
- package/src/server/handlers/tools/schemas.ts +253 -253
- package/src/server/handlers/tools/search-knowledge-graph.ts +102 -102
- package/src/server/handlers/tools/smart-context.ts +146 -146
- package/src/server/handlers/tools/update-progress.ts +131 -131
- package/src/server/handlers/tools/what-if-analysis.ts +135 -135
- package/src/server/http-api.ts +693 -693
- package/src/server/index.ts +40 -40
- package/src/server/mcp-server.ts +283 -283
- package/src/server/providers/index.ts +7 -7
- package/src/server/providers/prompts.ts +327 -327
- package/src/server/providers/resources.ts +622 -622
- package/src/server/services.ts +468 -468
- package/src/server/types.ts +39 -39
- package/src/server/utils/error-handler.ts +155 -155
- package/src/server/utils/index.ts +13 -13
- package/src/server/utils/memory-indicator.ts +83 -83
- package/src/server/utils/request-context.ts +122 -122
- package/src/server/utils/response-formatter.ts +129 -124
- package/src/server/utils/validators.ts +210 -210
- package/src/setup/index.ts +48 -48
- package/src/setup/wizard.ts +461 -461
- package/src/tools/index.ts +24 -24
- package/src/tools/registry.ts +115 -115
- package/src/tools/schemas.test.ts +30 -30
- package/src/tools/schemas.ts +617 -617
- package/src/tools/types.ts +412 -412
- package/src/utils/circuit-breaker.ts +130 -130
- package/src/utils/cleanup.ts +34 -34
- package/src/utils/error-handler.ts +132 -132
- package/src/utils/error-messages.ts +60 -60
- package/src/utils/fallback.ts +45 -45
- package/src/utils/index.ts +54 -54
- package/src/utils/logger-utils.ts +80 -80
- package/src/utils/logger.ts +88 -88
- package/src/utils/phase12-helper.ts +56 -56
- package/src/utils/retry.ts +94 -94
- package/src/utils/timing.ts +47 -47
- package/src/utils/transaction.ts +63 -63
- package/src/vault/frontmatter.ts +264 -264
- package/src/vault/index.ts +318 -318
- package/src/vault/paths.ts +106 -106
- package/src/vault/query.ts +422 -422
- package/src/vault/reader.ts +264 -264
- package/src/vault/templates.ts +186 -186
- package/src/vault/types.ts +73 -73
- package/src/vault/watcher.ts +277 -277
- package/src/vault/writer.ts +413 -413
- package/tsconfig.json +30 -30
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Search Knowledge Graph Handler
|
|
3
|
-
* Searches the knowledge graph for related nodes and edges
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Logger } from 'pino'
|
|
7
|
-
import type { ToolResponse } from '@/tools/types'
|
|
8
|
-
import { getKnowledgeGraphService, getMemoryService, isServicesInitialized } from '@/server/services'
|
|
9
|
-
import { ToolValidator } from '@/server/utils/validators'
|
|
10
|
-
import { ResponseFormatter } from '@/server/utils/response-formatter'
|
|
11
|
-
import { ErrorHandler } from '@/server/utils/error-handler'
|
|
12
|
-
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'
|
|
13
|
-
import { SearchKnowledgeGraphSchema } from './schemas'
|
|
14
|
-
|
|
15
|
-
export async function handleSearchKnowledgeGraph(
|
|
16
|
-
args: unknown,
|
|
17
|
-
logger: Logger
|
|
18
|
-
): Promise<ToolResponse> {
|
|
19
|
-
try {
|
|
20
|
-
const input = ToolValidator.validate(args, SearchKnowledgeGraphSchema)
|
|
21
|
-
const { query, node_type, start_node_id, hops, limit } = input
|
|
22
|
-
|
|
23
|
-
logger.debug({ query, nodeType: node_type, hops, limit }, 'Searching knowledge graph')
|
|
24
|
-
|
|
25
|
-
if (!isServicesInitialized()) {
|
|
26
|
-
throw new McpError(
|
|
27
|
-
ErrorCode.InternalError,
|
|
28
|
-
'Services not initialized. The server may still be starting up.'
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const kgService = getKnowledgeGraphService()
|
|
33
|
-
if (!kgService) {
|
|
34
|
-
return ResponseFormatter.text(
|
|
35
|
-
'Knowledge graph is not enabled. Enable it by setting knowledge.graph.enabled=true in config.'
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = kgService.search.search({
|
|
40
|
-
query,
|
|
41
|
-
nodeType: node_type as any,
|
|
42
|
-
startNodeId: start_node_id,
|
|
43
|
-
hops,
|
|
44
|
-
limit
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const formattedNodes = result.nodes.map(n => ({
|
|
48
|
-
id: n.id,
|
|
49
|
-
name: n.name,
|
|
50
|
-
type: n.type,
|
|
51
|
-
properties: n.properties,
|
|
52
|
-
score: result.scores.get(n.id) || 0
|
|
53
|
-
}))
|
|
54
|
-
|
|
55
|
-
const formattedEdges = result.edges.map(e => ({
|
|
56
|
-
source: e.source,
|
|
57
|
-
target: e.target,
|
|
58
|
-
relationship: e.relationship,
|
|
59
|
-
weight: e.weight
|
|
60
|
-
}))
|
|
61
|
-
|
|
62
|
-
const response = {
|
|
63
|
-
nodes: formattedNodes,
|
|
64
|
-
edges: formattedEdges,
|
|
65
|
-
paths: result.paths,
|
|
66
|
-
total_nodes: result.nodes.length,
|
|
67
|
-
total_edges: result.edges.length
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
logger.info({
|
|
71
|
-
nodeCount: result.nodes.length,
|
|
72
|
-
edgeCount: result.edges.length
|
|
73
|
-
}, 'Knowledge graph search complete')
|
|
74
|
-
|
|
75
|
-
// If graph is empty and ChromaDB is not connected, add guidance
|
|
76
|
-
if (result.nodes.length === 0 && result.edges.length === 0) {
|
|
77
|
-
const memory = getMemoryService()
|
|
78
|
-
if (!memory.isChromaDBEnabled()) {
|
|
79
|
-
return ResponseFormatter.text(
|
|
80
|
-
'Knowledge graph is empty (0 nodes, 0 edges).\n\n' +
|
|
81
|
-
'Note: ChromaDB is not connected. The knowledge graph is populated from stored decisions. ' +
|
|
82
|
-
'New decisions stored via SQLite will populate the graph going forward. ' +
|
|
83
|
-
'To migrate existing decisions into the graph, start a ChromaDB server or configure persistent mode.'
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return ResponseFormatter.json(response, 'Knowledge Graph Search Results')
|
|
89
|
-
|
|
90
|
-
} catch (error) {
|
|
91
|
-
ErrorHandler.logError(logger, error, { tool: 'search_knowledge_graph', args })
|
|
92
|
-
|
|
93
|
-
if (error instanceof McpError) {
|
|
94
|
-
throw error
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
throw new McpError(
|
|
98
|
-
ErrorCode.InternalError,
|
|
99
|
-
`Failed to search knowledge graph: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Search Knowledge Graph Handler
|
|
3
|
+
* Searches the knowledge graph for related nodes and edges
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Logger } from 'pino'
|
|
7
|
+
import type { ToolResponse } from '@/tools/types'
|
|
8
|
+
import { getKnowledgeGraphService, getMemoryService, isServicesInitialized } from '@/server/services'
|
|
9
|
+
import { ToolValidator } from '@/server/utils/validators'
|
|
10
|
+
import { ResponseFormatter } from '@/server/utils/response-formatter'
|
|
11
|
+
import { ErrorHandler } from '@/server/utils/error-handler'
|
|
12
|
+
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'
|
|
13
|
+
import { SearchKnowledgeGraphSchema } from './schemas'
|
|
14
|
+
|
|
15
|
+
export async function handleSearchKnowledgeGraph(
|
|
16
|
+
args: unknown,
|
|
17
|
+
logger: Logger
|
|
18
|
+
): Promise<ToolResponse> {
|
|
19
|
+
try {
|
|
20
|
+
const input = ToolValidator.validate(args, SearchKnowledgeGraphSchema)
|
|
21
|
+
const { query, node_type, start_node_id, hops, limit } = input
|
|
22
|
+
|
|
23
|
+
logger.debug({ query, nodeType: node_type, hops, limit }, 'Searching knowledge graph')
|
|
24
|
+
|
|
25
|
+
if (!isServicesInitialized()) {
|
|
26
|
+
throw new McpError(
|
|
27
|
+
ErrorCode.InternalError,
|
|
28
|
+
'Services not initialized. The server may still be starting up.'
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const kgService = getKnowledgeGraphService()
|
|
33
|
+
if (!kgService) {
|
|
34
|
+
return ResponseFormatter.text(
|
|
35
|
+
'Knowledge graph is not enabled. Enable it by setting knowledge.graph.enabled=true in config.'
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const result = kgService.search.search({
|
|
40
|
+
query,
|
|
41
|
+
nodeType: node_type as any,
|
|
42
|
+
startNodeId: start_node_id,
|
|
43
|
+
hops,
|
|
44
|
+
limit
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const formattedNodes = result.nodes.map(n => ({
|
|
48
|
+
id: n.id,
|
|
49
|
+
name: n.name,
|
|
50
|
+
type: n.type,
|
|
51
|
+
properties: n.properties,
|
|
52
|
+
score: result.scores.get(n.id) || 0
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
const formattedEdges = result.edges.map(e => ({
|
|
56
|
+
source: e.source,
|
|
57
|
+
target: e.target,
|
|
58
|
+
relationship: e.relationship,
|
|
59
|
+
weight: e.weight
|
|
60
|
+
}))
|
|
61
|
+
|
|
62
|
+
const response = {
|
|
63
|
+
nodes: formattedNodes,
|
|
64
|
+
edges: formattedEdges,
|
|
65
|
+
paths: result.paths,
|
|
66
|
+
total_nodes: result.nodes.length,
|
|
67
|
+
total_edges: result.edges.length
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
logger.info({
|
|
71
|
+
nodeCount: result.nodes.length,
|
|
72
|
+
edgeCount: result.edges.length
|
|
73
|
+
}, 'Knowledge graph search complete')
|
|
74
|
+
|
|
75
|
+
// If graph is empty and ChromaDB is not connected, add guidance
|
|
76
|
+
if (result.nodes.length === 0 && result.edges.length === 0) {
|
|
77
|
+
const memory = getMemoryService()
|
|
78
|
+
if (!memory.isChromaDBEnabled()) {
|
|
79
|
+
return ResponseFormatter.text(
|
|
80
|
+
'Knowledge graph is empty (0 nodes, 0 edges).\n\n' +
|
|
81
|
+
'Note: ChromaDB is not connected. The knowledge graph is populated from stored decisions. ' +
|
|
82
|
+
'New decisions stored via SQLite will populate the graph going forward. ' +
|
|
83
|
+
'To migrate existing decisions into the graph, start a ChromaDB server or configure persistent mode.'
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return ResponseFormatter.json(response, 'Knowledge Graph Search Results')
|
|
89
|
+
|
|
90
|
+
} catch (error) {
|
|
91
|
+
ErrorHandler.logError(logger, error, { tool: 'search_knowledge_graph', args })
|
|
92
|
+
|
|
93
|
+
if (error instanceof McpError) {
|
|
94
|
+
throw error
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
throw new McpError(
|
|
98
|
+
ErrorCode.InternalError,
|
|
99
|
+
`Failed to search knowledge graph: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smart Context Handler
|
|
3
|
-
* Gets project context + proactive memory recall based on current task
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Logger } from 'pino'
|
|
7
|
-
import type { ToolResponse } from '@/tools/types'
|
|
8
|
-
import { getContextService, getPhase12Service, getMemoryService, isServicesInitialized } from '@/server/services'
|
|
9
|
-
import { ToolValidator } from '@/server/utils/validators'
|
|
10
|
-
import { ResponseFormatter } from '@/server/utils/response-formatter'
|
|
11
|
-
import { withMemoryIndicator, formatMemoryStats } from '@/server/utils/memory-indicator'
|
|
12
|
-
import { ErrorHandler } from '@/server/utils/error-handler'
|
|
13
|
-
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'
|
|
14
|
-
import { SmartContextSchema } from './schemas'
|
|
15
|
-
|
|
16
|
-
export async function handleSmartContext(
|
|
17
|
-
args: unknown,
|
|
18
|
-
logger: Logger
|
|
19
|
-
): Promise<ToolResponse> {
|
|
20
|
-
try {
|
|
21
|
-
const input = ToolValidator.validate(args, SmartContextSchema)
|
|
22
|
-
const { project_name, current_task, min_similarity } = input
|
|
23
|
-
|
|
24
|
-
logger.debug({
|
|
25
|
-
project_name,
|
|
26
|
-
current_task: current_task.slice(0, 50),
|
|
27
|
-
min_similarity
|
|
28
|
-
}, 'Smart context request')
|
|
29
|
-
|
|
30
|
-
if (!isServicesInitialized()) {
|
|
31
|
-
throw new McpError(
|
|
32
|
-
ErrorCode.InternalError,
|
|
33
|
-
'Services not initialized'
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const contextService = getContextService()
|
|
38
|
-
const phase12 = getPhase12Service()
|
|
39
|
-
|
|
40
|
-
// Set current project in Phase 12 (use project name directly since we're getting it from user)
|
|
41
|
-
// The autoContext will be updated when context is loaded below
|
|
42
|
-
|
|
43
|
-
// Get base project context
|
|
44
|
-
const context = await contextService.getContext(project_name, {
|
|
45
|
-
includeMemories: false, // We'll use Phase 12 for smarter recall
|
|
46
|
-
includeProgress: true,
|
|
47
|
-
includeStandards: true,
|
|
48
|
-
maxTokens: 6000,
|
|
49
|
-
relevanceThreshold: 0.5
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
// Process with Phase 12 for proactive recall
|
|
53
|
-
const phase12Result = await phase12.processMessage(current_task, project_name)
|
|
54
|
-
|
|
55
|
-
// If Phase12's gated recall found nothing, do direct search (like recall_similar)
|
|
56
|
-
if (!phase12Result.recalledMemories || phase12Result.recalledMemories.memories.length === 0) {
|
|
57
|
-
try {
|
|
58
|
-
const memory = getMemoryService()
|
|
59
|
-
const directRecall = await memory.searchRaw(current_task, {
|
|
60
|
-
project: project_name,
|
|
61
|
-
limit: 5,
|
|
62
|
-
minSimilarity: min_similarity || 0.3
|
|
63
|
-
})
|
|
64
|
-
if (directRecall.length > 0) {
|
|
65
|
-
phase12Result.recalledMemories = {
|
|
66
|
-
query: current_task,
|
|
67
|
-
memories: directRecall,
|
|
68
|
-
relevanceScore: directRecall.reduce((sum: number, m: any) => sum + (m.similarity || 0), 0) / directRecall.length,
|
|
69
|
-
triggeredBy: ['direct-search-fallback']
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
} catch (e) {
|
|
73
|
-
logger.debug({ error: e }, 'Direct recall fallback failed, continuing without')
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Format base context
|
|
78
|
-
const formattedContext = contextService.formatter.format(context)
|
|
79
|
-
|
|
80
|
-
// Build response
|
|
81
|
-
const parts: string[] = []
|
|
82
|
-
parts.push(formattedContext)
|
|
83
|
-
parts.push('\n---\n')
|
|
84
|
-
parts.push('## 🧠 Intelligent Context (Phase 12)\n')
|
|
85
|
-
|
|
86
|
-
// Add proactive recall results
|
|
87
|
-
if (phase12Result.recalledMemories && phase12Result.recalledMemories.memories.length > 0) {
|
|
88
|
-
parts.push('### Relevant Past Decisions\n')
|
|
89
|
-
parts.push(`*Automatically recalled for: "${current_task.slice(0, 50)}${current_task.length > 50 ? '...' : ''}"*\n`)
|
|
90
|
-
|
|
91
|
-
for (const memory of phase12Result.recalledMemories.memories) {
|
|
92
|
-
const similarity = Math.round(memory.similarity * 100)
|
|
93
|
-
parts.push(`\n**[${similarity}% match]** ${memory.decision?.decision || memory.content.slice(0, 100)}`)
|
|
94
|
-
if (memory.decision?.reasoning) {
|
|
95
|
-
parts.push(`\n- *Reasoning:* ${memory.decision.reasoning}`)
|
|
96
|
-
}
|
|
97
|
-
if (memory.decision?.context) {
|
|
98
|
-
parts.push(`\n- *Context:* ${memory.decision.context}`)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
parts.push('\n')
|
|
102
|
-
} else {
|
|
103
|
-
parts.push('*No relevant past decisions found for this task.*\n')
|
|
104
|
-
parts.push('*Tip: As you make decisions, use `remember_decision` or `auto_remember` to build up your knowledge base.*\n')
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Add extracted knowledge if any
|
|
108
|
-
if (phase12Result.extractedKnowledge && phase12Result.extractedKnowledge.length > 0) {
|
|
109
|
-
parts.push('\n### Extracted Knowledge\n')
|
|
110
|
-
for (const k of phase12Result.extractedKnowledge) {
|
|
111
|
-
parts.push(`- **${k.type}:** ${k.content.slice(0, 100)}`)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const recalledCount = phase12Result.recalledMemories?.memories.length || 0
|
|
116
|
-
const knowledgeCount = phase12Result.extractedKnowledge?.length || 0
|
|
117
|
-
|
|
118
|
-
logger.info({
|
|
119
|
-
project_name,
|
|
120
|
-
recalledCount,
|
|
121
|
-
knowledgeCount
|
|
122
|
-
}, 'Smart context retrieved')
|
|
123
|
-
|
|
124
|
-
const content = parts.join('\n')
|
|
125
|
-
|
|
126
|
-
// Add memory indicator if we found helpful memories
|
|
127
|
-
if (recalledCount > 0) {
|
|
128
|
-
const statsLine = formatMemoryStats({ recalled: recalledCount })
|
|
129
|
-
return ResponseFormatter.text(withMemoryIndicator(content, recalledCount) + '\n\n' + statsLine)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return ResponseFormatter.text(content)
|
|
133
|
-
|
|
134
|
-
} catch (error) {
|
|
135
|
-
ErrorHandler.logError(logger, error, { tool: 'smart_context', args })
|
|
136
|
-
|
|
137
|
-
if (error instanceof McpError) {
|
|
138
|
-
throw error
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
throw new McpError(
|
|
142
|
-
ErrorCode.InternalError,
|
|
143
|
-
`Smart context failed: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
144
|
-
)
|
|
145
|
-
}
|
|
146
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Smart Context Handler
|
|
3
|
+
* Gets project context + proactive memory recall based on current task
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Logger } from 'pino'
|
|
7
|
+
import type { ToolResponse } from '@/tools/types'
|
|
8
|
+
import { getContextService, getPhase12Service, getMemoryService, isServicesInitialized } from '@/server/services'
|
|
9
|
+
import { ToolValidator } from '@/server/utils/validators'
|
|
10
|
+
import { ResponseFormatter } from '@/server/utils/response-formatter'
|
|
11
|
+
import { withMemoryIndicator, formatMemoryStats } from '@/server/utils/memory-indicator'
|
|
12
|
+
import { ErrorHandler } from '@/server/utils/error-handler'
|
|
13
|
+
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'
|
|
14
|
+
import { SmartContextSchema } from './schemas'
|
|
15
|
+
|
|
16
|
+
export async function handleSmartContext(
|
|
17
|
+
args: unknown,
|
|
18
|
+
logger: Logger
|
|
19
|
+
): Promise<ToolResponse> {
|
|
20
|
+
try {
|
|
21
|
+
const input = ToolValidator.validate(args, SmartContextSchema)
|
|
22
|
+
const { project_name, current_task, min_similarity } = input
|
|
23
|
+
|
|
24
|
+
logger.debug({
|
|
25
|
+
project_name,
|
|
26
|
+
current_task: current_task.slice(0, 50),
|
|
27
|
+
min_similarity
|
|
28
|
+
}, 'Smart context request')
|
|
29
|
+
|
|
30
|
+
if (!isServicesInitialized()) {
|
|
31
|
+
throw new McpError(
|
|
32
|
+
ErrorCode.InternalError,
|
|
33
|
+
'Services not initialized'
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const contextService = getContextService()
|
|
38
|
+
const phase12 = getPhase12Service()
|
|
39
|
+
|
|
40
|
+
// Set current project in Phase 12 (use project name directly since we're getting it from user)
|
|
41
|
+
// The autoContext will be updated when context is loaded below
|
|
42
|
+
|
|
43
|
+
// Get base project context
|
|
44
|
+
const context = await contextService.getContext(project_name, {
|
|
45
|
+
includeMemories: false, // We'll use Phase 12 for smarter recall
|
|
46
|
+
includeProgress: true,
|
|
47
|
+
includeStandards: true,
|
|
48
|
+
maxTokens: 6000,
|
|
49
|
+
relevanceThreshold: 0.5
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// Process with Phase 12 for proactive recall
|
|
53
|
+
const phase12Result = await phase12.processMessage(current_task, project_name)
|
|
54
|
+
|
|
55
|
+
// If Phase12's gated recall found nothing, do direct search (like recall_similar)
|
|
56
|
+
if (!phase12Result.recalledMemories || phase12Result.recalledMemories.memories.length === 0) {
|
|
57
|
+
try {
|
|
58
|
+
const memory = getMemoryService()
|
|
59
|
+
const directRecall = await memory.searchRaw(current_task, {
|
|
60
|
+
project: project_name,
|
|
61
|
+
limit: 5,
|
|
62
|
+
minSimilarity: min_similarity || 0.3
|
|
63
|
+
})
|
|
64
|
+
if (directRecall.length > 0) {
|
|
65
|
+
phase12Result.recalledMemories = {
|
|
66
|
+
query: current_task,
|
|
67
|
+
memories: directRecall,
|
|
68
|
+
relevanceScore: directRecall.reduce((sum: number, m: any) => sum + (m.similarity || 0), 0) / directRecall.length,
|
|
69
|
+
triggeredBy: ['direct-search-fallback']
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
logger.debug({ error: e }, 'Direct recall fallback failed, continuing without')
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Format base context
|
|
78
|
+
const formattedContext = contextService.formatter.format(context)
|
|
79
|
+
|
|
80
|
+
// Build response
|
|
81
|
+
const parts: string[] = []
|
|
82
|
+
parts.push(formattedContext)
|
|
83
|
+
parts.push('\n---\n')
|
|
84
|
+
parts.push('## 🧠 Intelligent Context (Phase 12)\n')
|
|
85
|
+
|
|
86
|
+
// Add proactive recall results
|
|
87
|
+
if (phase12Result.recalledMemories && phase12Result.recalledMemories.memories.length > 0) {
|
|
88
|
+
parts.push('### Relevant Past Decisions\n')
|
|
89
|
+
parts.push(`*Automatically recalled for: "${current_task.slice(0, 50)}${current_task.length > 50 ? '...' : ''}"*\n`)
|
|
90
|
+
|
|
91
|
+
for (const memory of phase12Result.recalledMemories.memories) {
|
|
92
|
+
const similarity = Math.round(memory.similarity * 100)
|
|
93
|
+
parts.push(`\n**[${similarity}% match]** ${memory.decision?.decision || memory.content.slice(0, 100)}`)
|
|
94
|
+
if (memory.decision?.reasoning) {
|
|
95
|
+
parts.push(`\n- *Reasoning:* ${memory.decision.reasoning}`)
|
|
96
|
+
}
|
|
97
|
+
if (memory.decision?.context) {
|
|
98
|
+
parts.push(`\n- *Context:* ${memory.decision.context}`)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
parts.push('\n')
|
|
102
|
+
} else {
|
|
103
|
+
parts.push('*No relevant past decisions found for this task.*\n')
|
|
104
|
+
parts.push('*Tip: As you make decisions, use `remember_decision` or `auto_remember` to build up your knowledge base.*\n')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Add extracted knowledge if any
|
|
108
|
+
if (phase12Result.extractedKnowledge && phase12Result.extractedKnowledge.length > 0) {
|
|
109
|
+
parts.push('\n### Extracted Knowledge\n')
|
|
110
|
+
for (const k of phase12Result.extractedKnowledge) {
|
|
111
|
+
parts.push(`- **${k.type}:** ${k.content.slice(0, 100)}`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const recalledCount = phase12Result.recalledMemories?.memories.length || 0
|
|
116
|
+
const knowledgeCount = phase12Result.extractedKnowledge?.length || 0
|
|
117
|
+
|
|
118
|
+
logger.info({
|
|
119
|
+
project_name,
|
|
120
|
+
recalledCount,
|
|
121
|
+
knowledgeCount
|
|
122
|
+
}, 'Smart context retrieved')
|
|
123
|
+
|
|
124
|
+
const content = parts.join('\n')
|
|
125
|
+
|
|
126
|
+
// Add memory indicator if we found helpful memories
|
|
127
|
+
if (recalledCount > 0) {
|
|
128
|
+
const statsLine = formatMemoryStats({ recalled: recalledCount })
|
|
129
|
+
return ResponseFormatter.text(withMemoryIndicator(content, recalledCount) + '\n\n' + statsLine)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return ResponseFormatter.text(content)
|
|
133
|
+
|
|
134
|
+
} catch (error) {
|
|
135
|
+
ErrorHandler.logError(logger, error, { tool: 'smart_context', args })
|
|
136
|
+
|
|
137
|
+
if (error instanceof McpError) {
|
|
138
|
+
throw error
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
throw new McpError(
|
|
142
|
+
ErrorCode.InternalError,
|
|
143
|
+
`Smart context failed: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|