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,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:
|
|
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.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: Record<string, unknown>) => sum + ((m.similarity as number) || 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.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,131 +1,131 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Update Progress Handler
|
|
3
|
-
* Updates project progress tracking with completed tasks and next steps
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Logger } from 'pino'
|
|
7
|
-
import type { ToolResponse } from '@/tools/types'
|
|
8
|
-
import { getVaultService, getContextService } 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 { UpdateProgressSchema } from './schemas'
|
|
14
|
-
|
|
15
|
-
export async function handleUpdateProgress(
|
|
16
|
-
args: unknown,
|
|
17
|
-
logger: Logger
|
|
18
|
-
): Promise<ToolResponse> {
|
|
19
|
-
try {
|
|
20
|
-
const input = ToolValidator.validate(args, UpdateProgressSchema)
|
|
21
|
-
const { project_name, completed_task, next_steps, notes } = input
|
|
22
|
-
|
|
23
|
-
logger.debug({
|
|
24
|
-
project_name,
|
|
25
|
-
completed_task,
|
|
26
|
-
next_steps,
|
|
27
|
-
hasNotes: !!notes
|
|
28
|
-
}, 'Updating progress')
|
|
29
|
-
|
|
30
|
-
const vault = getVaultService()
|
|
31
|
-
const context = getContextService()
|
|
32
|
-
|
|
33
|
-
const projectPaths = vault.getProjectPaths(project_name)
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await vault.reader.readMarkdownFile(projectPaths.progress)
|
|
37
|
-
} catch {
|
|
38
|
-
throw new McpError(
|
|
39
|
-
ErrorCode.InvalidParams,
|
|
40
|
-
`Project "${project_name}" not found. Progress file does not exist. Use list_projects to see available projects.`
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const taskId = generateTaskId(completed_task)
|
|
45
|
-
|
|
46
|
-
// Step 1: Append completed task to progress file
|
|
47
|
-
await context.progress.addCompletedTask(project_name, {
|
|
48
|
-
id: taskId,
|
|
49
|
-
title: completed_task,
|
|
50
|
-
status: 'done',
|
|
51
|
-
completedAt: new Date()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// Step 2: Read file bypassing cache, update next steps, write content
|
|
55
|
-
const progressFile = await vault.reader.readMarkdownFile(projectPaths.progress, false)
|
|
56
|
-
const updatedContent = updateNextStepsSection(progressFile.content, next_steps)
|
|
57
|
-
|
|
58
|
-
await vault.writer.writeMarkdownFile(
|
|
59
|
-
projectPaths.progress,
|
|
60
|
-
progressFile.frontmatter,
|
|
61
|
-
updatedContent,
|
|
62
|
-
{ createBackup: true }
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
// Step 3: Notes appended if present
|
|
66
|
-
if (notes) {
|
|
67
|
-
const notesEntry = `\n## Notes (${new Date().toLocaleDateString()})\n${notes}\n`
|
|
68
|
-
await vault.writer.appendContent(projectPaths.progress, notesEntry)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Step 4: Calculate and update frontmatter LAST (so nothing overwrites it)
|
|
72
|
-
const progressState = await context.progress.getProgress(project_name)
|
|
73
|
-
const totalTasks = progressState.completedTasks.length + progressState.currentTasks.length
|
|
74
|
-
const completionPercentage = totalTasks > 0
|
|
75
|
-
? Math.round((progressState.completedTasks.length / totalTasks) * 100)
|
|
76
|
-
: 0
|
|
77
|
-
|
|
78
|
-
await context.progress.updateProgress(project_name, {
|
|
79
|
-
completionPercentage,
|
|
80
|
-
currentPhase: completionPercentage >= 100 ? 'complete' : 'active'
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// Step 5: Invalidate cache so subsequent reads get fresh data
|
|
84
|
-
vault.reader.invalidateCache(projectPaths.progress)
|
|
85
|
-
context.invalidateContext(project_name)
|
|
86
|
-
|
|
87
|
-
logger.info({ projectName: project_name, taskId }, 'Progress updated successfully')
|
|
88
|
-
|
|
89
|
-
return ResponseFormatter.text(
|
|
90
|
-
`✅ Progress updated for ${project_name}\n\n` +
|
|
91
|
-
`**Completed:** ${completed_task}\n` +
|
|
92
|
-
`**Next Steps:** ${next_steps}\n` +
|
|
93
|
-
(notes ? `**Notes:** ${notes}\n` : '') +
|
|
94
|
-
`\nThe progress has been saved to your vault and context cache has been refreshed.`
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
} catch (error) {
|
|
98
|
-
ErrorHandler.logError(logger, error, { tool: 'update_progress', args })
|
|
99
|
-
|
|
100
|
-
if (error instanceof McpError) {
|
|
101
|
-
throw error
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
throw new McpError(
|
|
105
|
-
ErrorCode.InternalError,
|
|
106
|
-
`Failed to update progress: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function generateTaskId(title: string): string {
|
|
112
|
-
return title
|
|
113
|
-
.toLowerCase()
|
|
114
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
115
|
-
.replace(/^-+|-+$/g, '')
|
|
116
|
-
.slice(0, 50)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function updateNextStepsSection(content: string, nextSteps: string): string {
|
|
120
|
-
const nextStepsRegex = /##\s+Next Steps\s+(.+?)(?=\n##|$)/s
|
|
121
|
-
const match = nextStepsRegex.exec(content)
|
|
122
|
-
|
|
123
|
-
if (match) {
|
|
124
|
-
return content.replace(
|
|
125
|
-
nextStepsRegex,
|
|
126
|
-
`## Next Steps\n\n- ${nextSteps}\n`
|
|
127
|
-
)
|
|
128
|
-
} else {
|
|
129
|
-
return content + `\n\n## Next Steps\n\n- ${nextSteps}\n`
|
|
130
|
-
}
|
|
131
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Update Progress Handler
|
|
3
|
+
* Updates project progress tracking with completed tasks and next steps
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Logger } from 'pino'
|
|
7
|
+
import type { ToolResponse } from '@/tools/types'
|
|
8
|
+
import { getVaultService, getContextService } 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 { UpdateProgressSchema } from './schemas'
|
|
14
|
+
|
|
15
|
+
export async function handleUpdateProgress(
|
|
16
|
+
args: unknown,
|
|
17
|
+
logger: Logger
|
|
18
|
+
): Promise<ToolResponse> {
|
|
19
|
+
try {
|
|
20
|
+
const input = ToolValidator.validate(args, UpdateProgressSchema)
|
|
21
|
+
const { project_name, completed_task, next_steps, notes } = input
|
|
22
|
+
|
|
23
|
+
logger.debug({
|
|
24
|
+
project_name,
|
|
25
|
+
completed_task,
|
|
26
|
+
next_steps,
|
|
27
|
+
hasNotes: !!notes
|
|
28
|
+
}, 'Updating progress')
|
|
29
|
+
|
|
30
|
+
const vault = getVaultService()
|
|
31
|
+
const context = getContextService()
|
|
32
|
+
|
|
33
|
+
const projectPaths = vault.getProjectPaths(project_name)
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await vault.reader.readMarkdownFile(projectPaths.progress)
|
|
37
|
+
} catch {
|
|
38
|
+
throw new McpError(
|
|
39
|
+
ErrorCode.InvalidParams,
|
|
40
|
+
`Project "${project_name}" not found. Progress file does not exist. Use list_projects to see available projects.`
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const taskId = generateTaskId(completed_task)
|
|
45
|
+
|
|
46
|
+
// Step 1: Append completed task to progress file
|
|
47
|
+
await context.progress.addCompletedTask(project_name, {
|
|
48
|
+
id: taskId,
|
|
49
|
+
title: completed_task,
|
|
50
|
+
status: 'done',
|
|
51
|
+
completedAt: new Date()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Step 2: Read file bypassing cache, update next steps, write content
|
|
55
|
+
const progressFile = await vault.reader.readMarkdownFile(projectPaths.progress, false)
|
|
56
|
+
const updatedContent = updateNextStepsSection(progressFile.content, next_steps)
|
|
57
|
+
|
|
58
|
+
await vault.writer.writeMarkdownFile(
|
|
59
|
+
projectPaths.progress,
|
|
60
|
+
progressFile.frontmatter,
|
|
61
|
+
updatedContent,
|
|
62
|
+
{ createBackup: true }
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
// Step 3: Notes appended if present
|
|
66
|
+
if (notes) {
|
|
67
|
+
const notesEntry = `\n## Notes (${new Date().toLocaleDateString()})\n${notes}\n`
|
|
68
|
+
await vault.writer.appendContent(projectPaths.progress, notesEntry)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Step 4: Calculate and update frontmatter LAST (so nothing overwrites it)
|
|
72
|
+
const progressState = await context.progress.getProgress(project_name)
|
|
73
|
+
const totalTasks = progressState.completedTasks.length + progressState.currentTasks.length
|
|
74
|
+
const completionPercentage = totalTasks > 0
|
|
75
|
+
? Math.round((progressState.completedTasks.length / totalTasks) * 100)
|
|
76
|
+
: 0
|
|
77
|
+
|
|
78
|
+
await context.progress.updateProgress(project_name, {
|
|
79
|
+
completionPercentage,
|
|
80
|
+
currentPhase: completionPercentage >= 100 ? 'complete' : 'active'
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Step 5: Invalidate cache so subsequent reads get fresh data
|
|
84
|
+
vault.reader.invalidateCache(projectPaths.progress)
|
|
85
|
+
context.invalidateContext(project_name)
|
|
86
|
+
|
|
87
|
+
logger.info({ projectName: project_name, taskId }, 'Progress updated successfully')
|
|
88
|
+
|
|
89
|
+
return ResponseFormatter.text(
|
|
90
|
+
`✅ Progress updated for ${project_name}\n\n` +
|
|
91
|
+
`**Completed:** ${completed_task}\n` +
|
|
92
|
+
`**Next Steps:** ${next_steps}\n` +
|
|
93
|
+
(notes ? `**Notes:** ${notes}\n` : '') +
|
|
94
|
+
`\nThe progress has been saved to your vault and context cache has been refreshed.`
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
ErrorHandler.logError(logger, error, { tool: 'update_progress', args })
|
|
99
|
+
|
|
100
|
+
if (error instanceof McpError) {
|
|
101
|
+
throw error
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
throw new McpError(
|
|
105
|
+
ErrorCode.InternalError,
|
|
106
|
+
`Failed to update progress: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function generateTaskId(title: string): string {
|
|
112
|
+
return title
|
|
113
|
+
.toLowerCase()
|
|
114
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
115
|
+
.replace(/^-+|-+$/g, '')
|
|
116
|
+
.slice(0, 50)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function updateNextStepsSection(content: string, nextSteps: string): string {
|
|
120
|
+
const nextStepsRegex = /##\s+Next Steps\s+(.+?)(?=\n##|$)/s
|
|
121
|
+
const match = nextStepsRegex.exec(content)
|
|
122
|
+
|
|
123
|
+
if (match) {
|
|
124
|
+
return content.replace(
|
|
125
|
+
nextStepsRegex,
|
|
126
|
+
`## Next Steps\n\n- ${nextSteps}\n`
|
|
127
|
+
)
|
|
128
|
+
} else {
|
|
129
|
+
return content + `\n\n## Next Steps\n\n- ${nextSteps}\n`
|
|
130
|
+
}
|
|
131
|
+
}
|