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,151 +1,151 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analyze Decision Evolution Handler
|
|
3
|
-
* Tracks how decisions on a topic have evolved over time
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Logger } from 'pino'
|
|
7
|
-
import type { ToolResponse } from '@/tools/types'
|
|
8
|
-
import { getMemoryService } 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 { AnalyzeDecisionEvolutionSchema } from './schemas'
|
|
15
|
-
import { DecisionEvolutionTracker } from '@/intelligence/temporal/evolution'
|
|
16
|
-
|
|
17
|
-
export async function handleAnalyzeDecisionEvolution(
|
|
18
|
-
args: unknown,
|
|
19
|
-
logger: Logger
|
|
20
|
-
): Promise<ToolResponse> {
|
|
21
|
-
try {
|
|
22
|
-
const input = ToolValidator.validate(args, AnalyzeDecisionEvolutionSchema)
|
|
23
|
-
const { topic, project_name, limit } = input
|
|
24
|
-
|
|
25
|
-
const memory = getMemoryService()
|
|
26
|
-
|
|
27
|
-
if (!memory.isChromaDBEnabled()) {
|
|
28
|
-
// SQLite fallback: use searchRaw for semantic search + chronological analysis
|
|
29
|
-
const results = await memory.searchRaw(topic, {
|
|
30
|
-
project: project_name,
|
|
31
|
-
limit: limit || 20,
|
|
32
|
-
minSimilarity: 0.2
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
if (results.length === 0) {
|
|
36
|
-
return ResponseFormatter.text(`No decisions found for topic: "${topic}"`)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Sort chronologically
|
|
40
|
-
const sorted = results
|
|
41
|
-
.map(r => ({
|
|
42
|
-
date: r.memory?.createdAt?.toISOString?.() || r.memory?.created_at || new Date().toISOString(),
|
|
43
|
-
decision: r.decision?.decision || r.memory?.content || '',
|
|
44
|
-
reasoning: r.decision?.reasoning || '',
|
|
45
|
-
similarity: r.similarity || 0
|
|
46
|
-
}))
|
|
47
|
-
.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
|
|
48
|
-
|
|
49
|
-
// Simple stability assessment based on content similarity between consecutive decisions
|
|
50
|
-
let totalSimilarity = 0
|
|
51
|
-
let comparisons = 0
|
|
52
|
-
const changes: Array<{ daysBetween: number; summary: string }> = []
|
|
53
|
-
|
|
54
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
55
|
-
const prev = sorted[i - 1]
|
|
56
|
-
const curr = sorted[i]
|
|
57
|
-
const daysBetween = Math.round((new Date(curr.date).getTime() - new Date(prev.date).getTime()) / (1000 * 60 * 60 * 24))
|
|
58
|
-
|
|
59
|
-
// Simple Jaccard similarity between word sets
|
|
60
|
-
const prevWords = new Set(prev.decision.toLowerCase().split(/\s+/).filter(w => w.length > 3))
|
|
61
|
-
const currWords = new Set(curr.decision.toLowerCase().split(/\s+/).filter(w => w.length > 3))
|
|
62
|
-
const intersection = new Set([...prevWords].filter(w => currWords.has(w)))
|
|
63
|
-
const union = new Set([...prevWords, ...currWords])
|
|
64
|
-
const jaccard = union.size > 0 ? intersection.size / union.size : 0
|
|
65
|
-
totalSimilarity += jaccard
|
|
66
|
-
comparisons++
|
|
67
|
-
|
|
68
|
-
if (jaccard < 0.5) {
|
|
69
|
-
changes.push({
|
|
70
|
-
daysBetween,
|
|
71
|
-
summary: `Changed from "${prev.decision.slice(0, 60)}..." to "${curr.decision.slice(0, 60)}..."`
|
|
72
|
-
})
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const avgSimilarity = comparisons > 0 ? totalSimilarity / comparisons : 1
|
|
77
|
-
const stability = avgSimilarity > 0.7 ? 'stable' : avgSimilarity > 0.4 ? 'evolving' : 'volatile'
|
|
78
|
-
const currentState = sorted[sorted.length - 1].decision
|
|
79
|
-
|
|
80
|
-
const parts: string[] = []
|
|
81
|
-
parts.push(`## Decision Evolution: "${topic}" (SQLite)`)
|
|
82
|
-
if (project_name) parts.push(`**Project:** ${project_name}`)
|
|
83
|
-
parts.push(`**Total decisions:** ${sorted.length}`)
|
|
84
|
-
parts.push(`**Stability:** ${stability}`)
|
|
85
|
-
parts.push(`**Current state:** ${currentState.slice(0, 200)}`)
|
|
86
|
-
parts.push('')
|
|
87
|
-
|
|
88
|
-
if (changes.length > 0) {
|
|
89
|
-
parts.push('### Changes Over Time')
|
|
90
|
-
for (const change of changes) {
|
|
91
|
-
parts.push(`- **${change.daysBetween} days apart:** ${change.summary}`)
|
|
92
|
-
}
|
|
93
|
-
parts.push('')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
parts.push('### Timeline')
|
|
97
|
-
for (const entry of sorted.slice(0, 10)) {
|
|
98
|
-
const date = new Date(entry.date).toLocaleDateString()
|
|
99
|
-
parts.push(`- **${date}:** ${entry.decision.slice(0, 150)}`)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const statsLine = formatMemoryStats({ recalled: sorted.length })
|
|
103
|
-
return ResponseFormatter.text(withMemoryIndicator(parts.join('\n'), sorted.length) + '\n\n' + statsLine)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const tracker = new DecisionEvolutionTracker(
|
|
107
|
-
logger,
|
|
108
|
-
memory.chroma.collections,
|
|
109
|
-
memory.chroma.embeddings
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
const analysis = await tracker.analyzeEvolution(topic, {
|
|
113
|
-
project: project_name,
|
|
114
|
-
limit
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
if (analysis.totalDecisions === 0) {
|
|
118
|
-
return ResponseFormatter.text(`No decisions found for topic: "${topic}"`)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const parts: string[] = []
|
|
122
|
-
parts.push(`## Decision Evolution: "${topic}"`)
|
|
123
|
-
if (project_name) parts.push(`**Project:** ${project_name}`)
|
|
124
|
-
parts.push(`**Total decisions:** ${analysis.totalDecisions}`)
|
|
125
|
-
parts.push(`**Stability:** ${analysis.stability}`)
|
|
126
|
-
parts.push(`**Current state:** ${analysis.currentState.slice(0, 200)}`)
|
|
127
|
-
parts.push('')
|
|
128
|
-
|
|
129
|
-
if (analysis.changes.length > 0) {
|
|
130
|
-
parts.push('### Changes Over Time')
|
|
131
|
-
for (const change of analysis.changes) {
|
|
132
|
-
parts.push(`- **${change.daysBetween} days apart:** ${change.summary}`)
|
|
133
|
-
}
|
|
134
|
-
parts.push('')
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
parts.push('### Timeline')
|
|
138
|
-
for (const entry of analysis.timeline.slice(0, 10)) {
|
|
139
|
-
const date = new Date(entry.date).toLocaleDateString()
|
|
140
|
-
parts.push(`- **${date}:** ${entry.decision.slice(0, 150)}`)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const statsLine = formatMemoryStats({ recalled: analysis.totalDecisions })
|
|
144
|
-
return ResponseFormatter.text(withMemoryIndicator(parts.join('\n'), analysis.totalDecisions) + '\n\n' + statsLine)
|
|
145
|
-
|
|
146
|
-
} catch (error) {
|
|
147
|
-
ErrorHandler.logError(logger, error, { tool: 'analyze_decision_evolution' })
|
|
148
|
-
if (error instanceof McpError) throw error
|
|
149
|
-
throw new McpError(ErrorCode.InternalError, `Evolution analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Decision Evolution Handler
|
|
3
|
+
* Tracks how decisions on a topic have evolved over time
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Logger } from 'pino'
|
|
7
|
+
import type { ToolResponse } from '@/tools/types'
|
|
8
|
+
import { getMemoryService } 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 { AnalyzeDecisionEvolutionSchema } from './schemas'
|
|
15
|
+
import { DecisionEvolutionTracker } from '@/intelligence/temporal/evolution'
|
|
16
|
+
|
|
17
|
+
export async function handleAnalyzeDecisionEvolution(
|
|
18
|
+
args: unknown,
|
|
19
|
+
logger: Logger
|
|
20
|
+
): Promise<ToolResponse> {
|
|
21
|
+
try {
|
|
22
|
+
const input = ToolValidator.validate(args, AnalyzeDecisionEvolutionSchema)
|
|
23
|
+
const { topic, project_name, limit } = input
|
|
24
|
+
|
|
25
|
+
const memory = getMemoryService()
|
|
26
|
+
|
|
27
|
+
if (!memory.isChromaDBEnabled()) {
|
|
28
|
+
// SQLite fallback: use searchRaw for semantic search + chronological analysis
|
|
29
|
+
const results = await memory.searchRaw(topic, {
|
|
30
|
+
project: project_name,
|
|
31
|
+
limit: limit || 20,
|
|
32
|
+
minSimilarity: 0.2
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
if (results.length === 0) {
|
|
36
|
+
return ResponseFormatter.text(`No decisions found for topic: "${topic}"`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Sort chronologically
|
|
40
|
+
const sorted = results
|
|
41
|
+
.map(r => ({
|
|
42
|
+
date: r.memory?.createdAt?.toISOString?.() || r.memory?.created_at || new Date().toISOString(),
|
|
43
|
+
decision: r.decision?.decision || r.memory?.content || '',
|
|
44
|
+
reasoning: r.decision?.reasoning || '',
|
|
45
|
+
similarity: r.similarity || 0
|
|
46
|
+
}))
|
|
47
|
+
.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
|
|
48
|
+
|
|
49
|
+
// Simple stability assessment based on content similarity between consecutive decisions
|
|
50
|
+
let totalSimilarity = 0
|
|
51
|
+
let comparisons = 0
|
|
52
|
+
const changes: Array<{ daysBetween: number; summary: string }> = []
|
|
53
|
+
|
|
54
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
55
|
+
const prev = sorted[i - 1]
|
|
56
|
+
const curr = sorted[i]
|
|
57
|
+
const daysBetween = Math.round((new Date(curr.date).getTime() - new Date(prev.date).getTime()) / (1000 * 60 * 60 * 24))
|
|
58
|
+
|
|
59
|
+
// Simple Jaccard similarity between word sets
|
|
60
|
+
const prevWords = new Set(prev.decision.toLowerCase().split(/\s+/).filter(w => w.length > 3))
|
|
61
|
+
const currWords = new Set(curr.decision.toLowerCase().split(/\s+/).filter(w => w.length > 3))
|
|
62
|
+
const intersection = new Set([...prevWords].filter(w => currWords.has(w)))
|
|
63
|
+
const union = new Set([...prevWords, ...currWords])
|
|
64
|
+
const jaccard = union.size > 0 ? intersection.size / union.size : 0
|
|
65
|
+
totalSimilarity += jaccard
|
|
66
|
+
comparisons++
|
|
67
|
+
|
|
68
|
+
if (jaccard < 0.5) {
|
|
69
|
+
changes.push({
|
|
70
|
+
daysBetween,
|
|
71
|
+
summary: `Changed from "${prev.decision.slice(0, 60)}..." to "${curr.decision.slice(0, 60)}..."`
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const avgSimilarity = comparisons > 0 ? totalSimilarity / comparisons : 1
|
|
77
|
+
const stability = avgSimilarity > 0.7 ? 'stable' : avgSimilarity > 0.4 ? 'evolving' : 'volatile'
|
|
78
|
+
const currentState = sorted[sorted.length - 1].decision
|
|
79
|
+
|
|
80
|
+
const parts: string[] = []
|
|
81
|
+
parts.push(`## Decision Evolution: "${topic}" (SQLite)`)
|
|
82
|
+
if (project_name) parts.push(`**Project:** ${project_name}`)
|
|
83
|
+
parts.push(`**Total decisions:** ${sorted.length}`)
|
|
84
|
+
parts.push(`**Stability:** ${stability}`)
|
|
85
|
+
parts.push(`**Current state:** ${currentState.slice(0, 200)}`)
|
|
86
|
+
parts.push('')
|
|
87
|
+
|
|
88
|
+
if (changes.length > 0) {
|
|
89
|
+
parts.push('### Changes Over Time')
|
|
90
|
+
for (const change of changes) {
|
|
91
|
+
parts.push(`- **${change.daysBetween} days apart:** ${change.summary}`)
|
|
92
|
+
}
|
|
93
|
+
parts.push('')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
parts.push('### Timeline')
|
|
97
|
+
for (const entry of sorted.slice(0, 10)) {
|
|
98
|
+
const date = new Date(entry.date).toLocaleDateString()
|
|
99
|
+
parts.push(`- **${date}:** ${entry.decision.slice(0, 150)}`)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const statsLine = formatMemoryStats({ recalled: sorted.length })
|
|
103
|
+
return ResponseFormatter.text(withMemoryIndicator(parts.join('\n'), sorted.length) + '\n\n' + statsLine)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const tracker = new DecisionEvolutionTracker(
|
|
107
|
+
logger,
|
|
108
|
+
memory.chroma.collections,
|
|
109
|
+
memory.chroma.embeddings
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const analysis = await tracker.analyzeEvolution(topic, {
|
|
113
|
+
project: project_name,
|
|
114
|
+
limit
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if (analysis.totalDecisions === 0) {
|
|
118
|
+
return ResponseFormatter.text(`No decisions found for topic: "${topic}"`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const parts: string[] = []
|
|
122
|
+
parts.push(`## Decision Evolution: "${topic}"`)
|
|
123
|
+
if (project_name) parts.push(`**Project:** ${project_name}`)
|
|
124
|
+
parts.push(`**Total decisions:** ${analysis.totalDecisions}`)
|
|
125
|
+
parts.push(`**Stability:** ${analysis.stability}`)
|
|
126
|
+
parts.push(`**Current state:** ${analysis.currentState.slice(0, 200)}`)
|
|
127
|
+
parts.push('')
|
|
128
|
+
|
|
129
|
+
if (analysis.changes.length > 0) {
|
|
130
|
+
parts.push('### Changes Over Time')
|
|
131
|
+
for (const change of analysis.changes) {
|
|
132
|
+
parts.push(`- **${change.daysBetween} days apart:** ${change.summary}`)
|
|
133
|
+
}
|
|
134
|
+
parts.push('')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
parts.push('### Timeline')
|
|
138
|
+
for (const entry of analysis.timeline.slice(0, 10)) {
|
|
139
|
+
const date = new Date(entry.date).toLocaleDateString()
|
|
140
|
+
parts.push(`- **${date}:** ${entry.decision.slice(0, 150)}`)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const statsLine = formatMemoryStats({ recalled: analysis.totalDecisions })
|
|
144
|
+
return ResponseFormatter.text(withMemoryIndicator(parts.join('\n'), analysis.totalDecisions) + '\n\n' + statsLine)
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
ErrorHandler.logError(logger, error, { tool: 'analyze_decision_evolution' })
|
|
148
|
+
if (error instanceof McpError) throw error
|
|
149
|
+
throw new McpError(ErrorCode.InternalError, `Evolution analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`)
|
|
150
|
+
}
|
|
151
|
+
}
|