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,179 +1,179 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extractive Summarizer
|
|
3
|
-
* Generates summaries by scoring and selecting key sentences
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Episode, EpisodeSummary } from './types'
|
|
7
|
-
|
|
8
|
-
interface ScoredSentence {
|
|
9
|
-
text: string
|
|
10
|
-
score: number
|
|
11
|
-
position: number
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class ExtractiveSummarizer {
|
|
15
|
-
private briefSize: number
|
|
16
|
-
private detailedSize: number
|
|
17
|
-
|
|
18
|
-
constructor(briefSize: number = 2, detailedSize: number = 8) {
|
|
19
|
-
this.briefSize = briefSize
|
|
20
|
-
this.detailedSize = detailedSize
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
summarize(episode: Episode): EpisodeSummary {
|
|
24
|
-
const allText = episode.messages.map(m => m.content).join('\n')
|
|
25
|
-
const sentences = this.splitSentences(allText)
|
|
26
|
-
|
|
27
|
-
if (sentences.length === 0) {
|
|
28
|
-
return {
|
|
29
|
-
brief: 'Empty episode',
|
|
30
|
-
detailed: 'No messages in this episode.',
|
|
31
|
-
key_topics: [],
|
|
32
|
-
decisions_made: [],
|
|
33
|
-
unresolved_questions: [],
|
|
34
|
-
entity_count: 0
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Calculate word frequencies for TF scoring
|
|
39
|
-
const wordFreqs = this.calculateWordFrequencies(allText)
|
|
40
|
-
const totalSentences = sentences.length
|
|
41
|
-
|
|
42
|
-
// Score each sentence
|
|
43
|
-
const scored: ScoredSentence[] = sentences.map((text, position) => ({
|
|
44
|
-
text,
|
|
45
|
-
position,
|
|
46
|
-
score: this.scoreSentence(text, position, totalSentences, wordFreqs)
|
|
47
|
-
}))
|
|
48
|
-
|
|
49
|
-
// Sort by score descending
|
|
50
|
-
const ranked = [...scored].sort((a, b) => b.score - a.score)
|
|
51
|
-
|
|
52
|
-
// Select top sentences for brief and detailed, then re-order by position
|
|
53
|
-
const briefSentences = ranked
|
|
54
|
-
.slice(0, this.briefSize)
|
|
55
|
-
.sort((a, b) => a.position - b.position)
|
|
56
|
-
.map(s => s.text)
|
|
57
|
-
|
|
58
|
-
const detailedSentences = ranked
|
|
59
|
-
.slice(0, this.detailedSize)
|
|
60
|
-
.sort((a, b) => a.position - b.position)
|
|
61
|
-
.map(s => s.text)
|
|
62
|
-
|
|
63
|
-
// Extract key topics from high-frequency words
|
|
64
|
-
const keyTopics = this.extractKeyTopics(wordFreqs)
|
|
65
|
-
|
|
66
|
-
// Find decisions (sentences with decision keywords)
|
|
67
|
-
const decisionKeywords = ['decided', 'chose', 'selected', 'will use', 'going with', 'recommend', 'should use']
|
|
68
|
-
const decisions = sentences.filter(s =>
|
|
69
|
-
decisionKeywords.some(k => s.toLowerCase().includes(k))
|
|
70
|
-
).slice(0, 5)
|
|
71
|
-
|
|
72
|
-
// Find unresolved questions (last messages with ? that aren't answered)
|
|
73
|
-
const lastMessages = episode.messages.slice(-Math.ceil(episode.messages.length / 2))
|
|
74
|
-
const questions = lastMessages
|
|
75
|
-
.filter(m => m.role === 'user' && m.content.includes('?'))
|
|
76
|
-
.map(m => {
|
|
77
|
-
const qSentences = this.splitSentences(m.content)
|
|
78
|
-
return qSentences.filter(s => s.includes('?'))
|
|
79
|
-
})
|
|
80
|
-
.flat()
|
|
81
|
-
.slice(0, 3)
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
brief: briefSentences.join(' '),
|
|
85
|
-
detailed: detailedSentences.join(' '),
|
|
86
|
-
key_topics: keyTopics,
|
|
87
|
-
decisions_made: decisions,
|
|
88
|
-
unresolved_questions: questions,
|
|
89
|
-
entity_count: keyTopics.length
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private splitSentences(text: string): string[] {
|
|
94
|
-
// Split on sentence boundaries
|
|
95
|
-
const raw = text
|
|
96
|
-
.replace(/\n+/g, '. ')
|
|
97
|
-
.split(/(?<=[.!?])\s+/)
|
|
98
|
-
.map(s => s.trim())
|
|
99
|
-
.filter(s => s.length > 10)
|
|
100
|
-
|
|
101
|
-
return raw
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private calculateWordFrequencies(text: string): Map<string, number> {
|
|
105
|
-
const stopWords = new Set([
|
|
106
|
-
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
107
|
-
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
108
|
-
'should', 'can', 'may', 'might', 'to', 'of', 'in', 'for', 'on',
|
|
109
|
-
'with', 'at', 'by', 'from', 'as', 'and', 'but', 'or', 'not', 'so',
|
|
110
|
-
'if', 'that', 'this', 'it', 'its', 'i', 'me', 'my', 'we', 'our',
|
|
111
|
-
'you', 'your', 'he', 'she', 'they', 'them', 'their', 'what', 'which',
|
|
112
|
-
'who', 'when', 'where', 'how', 'all', 'each', 'both', 'few', 'more',
|
|
113
|
-
'most', 'other', 'some', 'no', 'only', 'own', 'same', 'than', 'too',
|
|
114
|
-
'very', 'just', 'about', 'up', 'out', 'off'
|
|
115
|
-
])
|
|
116
|
-
|
|
117
|
-
const freqs = new Map<string, number>()
|
|
118
|
-
const words = text.toLowerCase()
|
|
119
|
-
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
120
|
-
.split(/\s+/)
|
|
121
|
-
.filter(w => w.length > 2 && !stopWords.has(w))
|
|
122
|
-
|
|
123
|
-
for (const word of words) {
|
|
124
|
-
freqs.set(word, (freqs.get(word) || 0) + 1)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return freqs
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private scoreSentence(
|
|
131
|
-
sentence: string,
|
|
132
|
-
position: number,
|
|
133
|
-
totalSentences: number,
|
|
134
|
-
wordFreqs: Map<string, number>
|
|
135
|
-
): number {
|
|
136
|
-
let score = 0
|
|
137
|
-
|
|
138
|
-
// 1. TF-based keyword score
|
|
139
|
-
const words = sentence.toLowerCase()
|
|
140
|
-
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
141
|
-
.split(/\s+/)
|
|
142
|
-
.filter(w => w.length > 2)
|
|
143
|
-
|
|
144
|
-
if (words.length === 0) return 0
|
|
145
|
-
|
|
146
|
-
let keywordScore = 0
|
|
147
|
-
for (const word of words) {
|
|
148
|
-
keywordScore += wordFreqs.get(word) || 0
|
|
149
|
-
}
|
|
150
|
-
keywordScore /= words.length // normalize by sentence length
|
|
151
|
-
score += keywordScore * 0.4
|
|
152
|
-
|
|
153
|
-
// 2. Position bonus (first and last sentences score higher)
|
|
154
|
-
const posRatio = position / Math.max(totalSentences - 1, 1)
|
|
155
|
-
const positionScore = posRatio < 0.15 ? 1.0 : posRatio > 0.85 ? 0.8 : 0.3
|
|
156
|
-
score += positionScore * 0.25
|
|
157
|
-
|
|
158
|
-
// 3. Decision keyword boost
|
|
159
|
-
const decisionKeywords = ['decided', 'chose', 'selected', 'recommend', 'should', 'must', 'will use', 'going with', 'use', 'implement', 'adopt']
|
|
160
|
-
const lowerSentence = sentence.toLowerCase()
|
|
161
|
-
const hasDecision = decisionKeywords.some(k => lowerSentence.includes(k))
|
|
162
|
-
if (hasDecision) score += 0.2
|
|
163
|
-
|
|
164
|
-
// 4. Length penalty for very short or very long sentences
|
|
165
|
-
const optimalLength = 20 // words
|
|
166
|
-
const lengthRatio = Math.min(words.length, optimalLength * 2) / optimalLength
|
|
167
|
-
const lengthScore = lengthRatio <= 1 ? lengthRatio : 2 - lengthRatio
|
|
168
|
-
score += Math.max(0, lengthScore) * 0.15
|
|
169
|
-
|
|
170
|
-
return score
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
private extractKeyTopics(wordFreqs: Map<string, number>): string[] {
|
|
174
|
-
return Array.from(wordFreqs.entries())
|
|
175
|
-
.sort(([, a], [, b]) => b - a)
|
|
176
|
-
.slice(0, 10)
|
|
177
|
-
.map(([word]) => word)
|
|
178
|
-
}
|
|
179
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Extractive Summarizer
|
|
3
|
+
* Generates summaries by scoring and selecting key sentences
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Episode, EpisodeSummary } from './types'
|
|
7
|
+
|
|
8
|
+
interface ScoredSentence {
|
|
9
|
+
text: string
|
|
10
|
+
score: number
|
|
11
|
+
position: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class ExtractiveSummarizer {
|
|
15
|
+
private briefSize: number
|
|
16
|
+
private detailedSize: number
|
|
17
|
+
|
|
18
|
+
constructor(briefSize: number = 2, detailedSize: number = 8) {
|
|
19
|
+
this.briefSize = briefSize
|
|
20
|
+
this.detailedSize = detailedSize
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
summarize(episode: Episode): EpisodeSummary {
|
|
24
|
+
const allText = episode.messages.map(m => m.content).join('\n')
|
|
25
|
+
const sentences = this.splitSentences(allText)
|
|
26
|
+
|
|
27
|
+
if (sentences.length === 0) {
|
|
28
|
+
return {
|
|
29
|
+
brief: 'Empty episode',
|
|
30
|
+
detailed: 'No messages in this episode.',
|
|
31
|
+
key_topics: [],
|
|
32
|
+
decisions_made: [],
|
|
33
|
+
unresolved_questions: [],
|
|
34
|
+
entity_count: 0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Calculate word frequencies for TF scoring
|
|
39
|
+
const wordFreqs = this.calculateWordFrequencies(allText)
|
|
40
|
+
const totalSentences = sentences.length
|
|
41
|
+
|
|
42
|
+
// Score each sentence
|
|
43
|
+
const scored: ScoredSentence[] = sentences.map((text, position) => ({
|
|
44
|
+
text,
|
|
45
|
+
position,
|
|
46
|
+
score: this.scoreSentence(text, position, totalSentences, wordFreqs)
|
|
47
|
+
}))
|
|
48
|
+
|
|
49
|
+
// Sort by score descending
|
|
50
|
+
const ranked = [...scored].sort((a, b) => b.score - a.score)
|
|
51
|
+
|
|
52
|
+
// Select top sentences for brief and detailed, then re-order by position
|
|
53
|
+
const briefSentences = ranked
|
|
54
|
+
.slice(0, this.briefSize)
|
|
55
|
+
.sort((a, b) => a.position - b.position)
|
|
56
|
+
.map(s => s.text)
|
|
57
|
+
|
|
58
|
+
const detailedSentences = ranked
|
|
59
|
+
.slice(0, this.detailedSize)
|
|
60
|
+
.sort((a, b) => a.position - b.position)
|
|
61
|
+
.map(s => s.text)
|
|
62
|
+
|
|
63
|
+
// Extract key topics from high-frequency words
|
|
64
|
+
const keyTopics = this.extractKeyTopics(wordFreqs)
|
|
65
|
+
|
|
66
|
+
// Find decisions (sentences with decision keywords)
|
|
67
|
+
const decisionKeywords = ['decided', 'chose', 'selected', 'will use', 'going with', 'recommend', 'should use']
|
|
68
|
+
const decisions = sentences.filter(s =>
|
|
69
|
+
decisionKeywords.some(k => s.toLowerCase().includes(k))
|
|
70
|
+
).slice(0, 5)
|
|
71
|
+
|
|
72
|
+
// Find unresolved questions (last messages with ? that aren't answered)
|
|
73
|
+
const lastMessages = episode.messages.slice(-Math.ceil(episode.messages.length / 2))
|
|
74
|
+
const questions = lastMessages
|
|
75
|
+
.filter(m => m.role === 'user' && m.content.includes('?'))
|
|
76
|
+
.map(m => {
|
|
77
|
+
const qSentences = this.splitSentences(m.content)
|
|
78
|
+
return qSentences.filter(s => s.includes('?'))
|
|
79
|
+
})
|
|
80
|
+
.flat()
|
|
81
|
+
.slice(0, 3)
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
brief: briefSentences.join(' '),
|
|
85
|
+
detailed: detailedSentences.join(' '),
|
|
86
|
+
key_topics: keyTopics,
|
|
87
|
+
decisions_made: decisions,
|
|
88
|
+
unresolved_questions: questions,
|
|
89
|
+
entity_count: keyTopics.length
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private splitSentences(text: string): string[] {
|
|
94
|
+
// Split on sentence boundaries
|
|
95
|
+
const raw = text
|
|
96
|
+
.replace(/\n+/g, '. ')
|
|
97
|
+
.split(/(?<=[.!?])\s+/)
|
|
98
|
+
.map(s => s.trim())
|
|
99
|
+
.filter(s => s.length > 10)
|
|
100
|
+
|
|
101
|
+
return raw
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private calculateWordFrequencies(text: string): Map<string, number> {
|
|
105
|
+
const stopWords = new Set([
|
|
106
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
107
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
108
|
+
'should', 'can', 'may', 'might', 'to', 'of', 'in', 'for', 'on',
|
|
109
|
+
'with', 'at', 'by', 'from', 'as', 'and', 'but', 'or', 'not', 'so',
|
|
110
|
+
'if', 'that', 'this', 'it', 'its', 'i', 'me', 'my', 'we', 'our',
|
|
111
|
+
'you', 'your', 'he', 'she', 'they', 'them', 'their', 'what', 'which',
|
|
112
|
+
'who', 'when', 'where', 'how', 'all', 'each', 'both', 'few', 'more',
|
|
113
|
+
'most', 'other', 'some', 'no', 'only', 'own', 'same', 'than', 'too',
|
|
114
|
+
'very', 'just', 'about', 'up', 'out', 'off'
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
const freqs = new Map<string, number>()
|
|
118
|
+
const words = text.toLowerCase()
|
|
119
|
+
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
120
|
+
.split(/\s+/)
|
|
121
|
+
.filter(w => w.length > 2 && !stopWords.has(w))
|
|
122
|
+
|
|
123
|
+
for (const word of words) {
|
|
124
|
+
freqs.set(word, (freqs.get(word) || 0) + 1)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return freqs
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private scoreSentence(
|
|
131
|
+
sentence: string,
|
|
132
|
+
position: number,
|
|
133
|
+
totalSentences: number,
|
|
134
|
+
wordFreqs: Map<string, number>
|
|
135
|
+
): number {
|
|
136
|
+
let score = 0
|
|
137
|
+
|
|
138
|
+
// 1. TF-based keyword score
|
|
139
|
+
const words = sentence.toLowerCase()
|
|
140
|
+
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
141
|
+
.split(/\s+/)
|
|
142
|
+
.filter(w => w.length > 2)
|
|
143
|
+
|
|
144
|
+
if (words.length === 0) return 0
|
|
145
|
+
|
|
146
|
+
let keywordScore = 0
|
|
147
|
+
for (const word of words) {
|
|
148
|
+
keywordScore += wordFreqs.get(word) || 0
|
|
149
|
+
}
|
|
150
|
+
keywordScore /= words.length // normalize by sentence length
|
|
151
|
+
score += keywordScore * 0.4
|
|
152
|
+
|
|
153
|
+
// 2. Position bonus (first and last sentences score higher)
|
|
154
|
+
const posRatio = position / Math.max(totalSentences - 1, 1)
|
|
155
|
+
const positionScore = posRatio < 0.15 ? 1.0 : posRatio > 0.85 ? 0.8 : 0.3
|
|
156
|
+
score += positionScore * 0.25
|
|
157
|
+
|
|
158
|
+
// 3. Decision keyword boost
|
|
159
|
+
const decisionKeywords = ['decided', 'chose', 'selected', 'recommend', 'should', 'must', 'will use', 'going with', 'use', 'implement', 'adopt']
|
|
160
|
+
const lowerSentence = sentence.toLowerCase()
|
|
161
|
+
const hasDecision = decisionKeywords.some(k => lowerSentence.includes(k))
|
|
162
|
+
if (hasDecision) score += 0.2
|
|
163
|
+
|
|
164
|
+
// 4. Length penalty for very short or very long sentences
|
|
165
|
+
const optimalLength = 20 // words
|
|
166
|
+
const lengthRatio = Math.min(words.length, optimalLength * 2) / optimalLength
|
|
167
|
+
const lengthScore = lengthRatio <= 1 ? lengthRatio : 2 - lengthRatio
|
|
168
|
+
score += Math.max(0, lengthScore) * 0.15
|
|
169
|
+
|
|
170
|
+
return score
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private extractKeyTopics(wordFreqs: Map<string, number>): string[] {
|
|
174
|
+
return Array.from(wordFreqs.entries())
|
|
175
|
+
.sort(([, a], [, b]) => b - a)
|
|
176
|
+
.slice(0, 10)
|
|
177
|
+
.map(([word]) => word)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Episodic Memory Types
|
|
3
|
-
* Type definitions for the episodic memory system
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface EpisodeMessage {
|
|
7
|
-
role: 'user' | 'assistant' | 'system'
|
|
8
|
-
content: string
|
|
9
|
-
timestamp: string
|
|
10
|
-
token_estimate?: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface EpisodeSummary {
|
|
14
|
-
brief: string
|
|
15
|
-
detailed: string
|
|
16
|
-
key_topics: string[]
|
|
17
|
-
decisions_made: string[]
|
|
18
|
-
unresolved_questions: string[]
|
|
19
|
-
entity_count: number
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type SessionClassification = 'new_session' | 'continuation' | 'topic_shift'
|
|
23
|
-
|
|
24
|
-
export interface Episode {
|
|
25
|
-
id: string
|
|
26
|
-
project?: string
|
|
27
|
-
status: 'active' | 'completed'
|
|
28
|
-
started_at: string
|
|
29
|
-
ended_at?: string
|
|
30
|
-
messages: EpisodeMessage[]
|
|
31
|
-
summary?: EpisodeSummary
|
|
32
|
-
related_decisions: string[]
|
|
33
|
-
related_patterns: string[]
|
|
34
|
-
related_corrections: string[]
|
|
35
|
-
token_count: number
|
|
36
|
-
message_count: number
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface EpisodeMetadata {
|
|
40
|
-
episode_id: string
|
|
41
|
-
project: string
|
|
42
|
-
status: 'active' | 'completed'
|
|
43
|
-
started_at: string
|
|
44
|
-
ended_at: string
|
|
45
|
-
message_count: number
|
|
46
|
-
token_count: number
|
|
47
|
-
key_topics: string
|
|
48
|
-
brief_summary: string
|
|
49
|
-
related_decisions: string
|
|
50
|
-
related_patterns: string
|
|
51
|
-
related_corrections: string
|
|
52
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Episodic Memory Types
|
|
3
|
+
* Type definitions for the episodic memory system
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface EpisodeMessage {
|
|
7
|
+
role: 'user' | 'assistant' | 'system'
|
|
8
|
+
content: string
|
|
9
|
+
timestamp: string
|
|
10
|
+
token_estimate?: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface EpisodeSummary {
|
|
14
|
+
brief: string
|
|
15
|
+
detailed: string
|
|
16
|
+
key_topics: string[]
|
|
17
|
+
decisions_made: string[]
|
|
18
|
+
unresolved_questions: string[]
|
|
19
|
+
entity_count: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type SessionClassification = 'new_session' | 'continuation' | 'topic_shift'
|
|
23
|
+
|
|
24
|
+
export interface Episode {
|
|
25
|
+
id: string
|
|
26
|
+
project?: string
|
|
27
|
+
status: 'active' | 'completed'
|
|
28
|
+
started_at: string
|
|
29
|
+
ended_at?: string
|
|
30
|
+
messages: EpisodeMessage[]
|
|
31
|
+
summary?: EpisodeSummary
|
|
32
|
+
related_decisions: string[]
|
|
33
|
+
related_patterns: string[]
|
|
34
|
+
related_corrections: string[]
|
|
35
|
+
token_count: number
|
|
36
|
+
message_count: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface EpisodeMetadata {
|
|
40
|
+
episode_id: string
|
|
41
|
+
project: string
|
|
42
|
+
status: 'active' | 'completed'
|
|
43
|
+
started_at: string
|
|
44
|
+
ended_at: string
|
|
45
|
+
message_count: number
|
|
46
|
+
token_count: number
|
|
47
|
+
key_topics: string
|
|
48
|
+
brief_summary: string
|
|
49
|
+
related_decisions: string
|
|
50
|
+
related_patterns: string
|
|
51
|
+
related_corrections: string
|
|
52
|
+
}
|