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,131 +1,131 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StatusChangeHandler - Detects status changes in project files
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Logger } from 'pino'
|
|
6
|
-
import type { Event, EventType, EventPriority } from '../types'
|
|
7
|
-
import type { VaultReader } from '@/vault'
|
|
8
|
-
import { BaseHandler } from './base-handler'
|
|
9
|
-
import type { EventBus } from '../event-emitter'
|
|
10
|
-
|
|
11
|
-
export interface StatusChange {
|
|
12
|
-
filePath: string
|
|
13
|
-
previousStatus: string
|
|
14
|
-
currentStatus: string
|
|
15
|
-
project?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class StatusChangeHandler extends BaseHandler {
|
|
19
|
-
name = 'status-change-handler'
|
|
20
|
-
types: EventType[] = ['file:modified']
|
|
21
|
-
priority: EventPriority = 'normal'
|
|
22
|
-
|
|
23
|
-
private vaultReader: VaultReader
|
|
24
|
-
private previousStatuses: Map<string, string>
|
|
25
|
-
private eventBus: EventBus | null = null
|
|
26
|
-
|
|
27
|
-
constructor(logger: Logger, vaultReader: VaultReader) {
|
|
28
|
-
super(logger)
|
|
29
|
-
this.initLogger(logger)
|
|
30
|
-
this.vaultReader = vaultReader
|
|
31
|
-
this.previousStatuses = new Map()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Set the event bus for emitting status change events
|
|
36
|
-
*/
|
|
37
|
-
setEventBus(eventBus: EventBus): void {
|
|
38
|
-
this.eventBus = eventBus
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async handle(event: Event): Promise<void> {
|
|
42
|
-
this.logHandling(event)
|
|
43
|
-
|
|
44
|
-
const filePath = event.payload.path as string
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
// Read file and check for status changes
|
|
48
|
-
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
49
|
-
const currentStatus = file.frontmatter.status as string | undefined
|
|
50
|
-
|
|
51
|
-
if (!currentStatus) {
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const previousStatus = this.previousStatuses.get(filePath)
|
|
56
|
-
|
|
57
|
-
if (previousStatus && previousStatus !== currentStatus) {
|
|
58
|
-
const statusChange: StatusChange = {
|
|
59
|
-
filePath,
|
|
60
|
-
previousStatus,
|
|
61
|
-
currentStatus,
|
|
62
|
-
project: file.frontmatter.project as string | undefined
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.logger.info(
|
|
66
|
-
{ filePath, from: previousStatus, to: currentStatus },
|
|
67
|
-
'Status changed'
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
// Emit status change event if event bus is available
|
|
71
|
-
if (this.eventBus) {
|
|
72
|
-
this.eventBus.emitEvent(
|
|
73
|
-
'project:updated',
|
|
74
|
-
{
|
|
75
|
-
statusChange,
|
|
76
|
-
filePath,
|
|
77
|
-
project: file.frontmatter.project
|
|
78
|
-
},
|
|
79
|
-
this.name
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
this.logSuccess(event, { from: previousStatus, to: currentStatus })
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Update cached status
|
|
87
|
-
this.previousStatuses.set(filePath, currentStatus)
|
|
88
|
-
} catch (error) {
|
|
89
|
-
this.logError(event, error)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Initialize status tracking for a file
|
|
95
|
-
*/
|
|
96
|
-
async initializeStatus(filePath: string): Promise<void> {
|
|
97
|
-
try {
|
|
98
|
-
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
99
|
-
const status = file.frontmatter.status as string | undefined
|
|
100
|
-
|
|
101
|
-
if (status) {
|
|
102
|
-
this.previousStatuses.set(filePath, status)
|
|
103
|
-
this.logger.debug({ filePath, status }, 'Status initialized')
|
|
104
|
-
}
|
|
105
|
-
} catch (error) {
|
|
106
|
-
this.logger.warn({ filePath, error }, 'Failed to initialize status')
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get cached status for a file
|
|
112
|
-
*/
|
|
113
|
-
getCachedStatus(filePath: string): string | undefined {
|
|
114
|
-
return this.previousStatuses.get(filePath)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Clear status cache
|
|
119
|
-
*/
|
|
120
|
-
clearStatusCache(): void {
|
|
121
|
-
this.previousStatuses.clear()
|
|
122
|
-
this.logger.debug('Status cache cleared')
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get all tracked file paths
|
|
127
|
-
*/
|
|
128
|
-
getTrackedFiles(): string[] {
|
|
129
|
-
return Array.from(this.previousStatuses.keys())
|
|
130
|
-
}
|
|
131
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* StatusChangeHandler - Detects status changes in project files
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Logger } from 'pino'
|
|
6
|
+
import type { Event, EventType, EventPriority } from '../types'
|
|
7
|
+
import type { VaultReader } from '@/vault'
|
|
8
|
+
import { BaseHandler } from './base-handler'
|
|
9
|
+
import type { EventBus } from '../event-emitter'
|
|
10
|
+
|
|
11
|
+
export interface StatusChange {
|
|
12
|
+
filePath: string
|
|
13
|
+
previousStatus: string
|
|
14
|
+
currentStatus: string
|
|
15
|
+
project?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class StatusChangeHandler extends BaseHandler {
|
|
19
|
+
name = 'status-change-handler'
|
|
20
|
+
types: EventType[] = ['file:modified']
|
|
21
|
+
priority: EventPriority = 'normal'
|
|
22
|
+
|
|
23
|
+
private vaultReader: VaultReader
|
|
24
|
+
private previousStatuses: Map<string, string>
|
|
25
|
+
private eventBus: EventBus | null = null
|
|
26
|
+
|
|
27
|
+
constructor(logger: Logger, vaultReader: VaultReader) {
|
|
28
|
+
super(logger)
|
|
29
|
+
this.initLogger(logger)
|
|
30
|
+
this.vaultReader = vaultReader
|
|
31
|
+
this.previousStatuses = new Map()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Set the event bus for emitting status change events
|
|
36
|
+
*/
|
|
37
|
+
setEventBus(eventBus: EventBus): void {
|
|
38
|
+
this.eventBus = eventBus
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async handle(event: Event): Promise<void> {
|
|
42
|
+
this.logHandling(event)
|
|
43
|
+
|
|
44
|
+
const filePath = event.payload.path as string
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
// Read file and check for status changes
|
|
48
|
+
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
49
|
+
const currentStatus = file.frontmatter.status as string | undefined
|
|
50
|
+
|
|
51
|
+
if (!currentStatus) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const previousStatus = this.previousStatuses.get(filePath)
|
|
56
|
+
|
|
57
|
+
if (previousStatus && previousStatus !== currentStatus) {
|
|
58
|
+
const statusChange: StatusChange = {
|
|
59
|
+
filePath,
|
|
60
|
+
previousStatus,
|
|
61
|
+
currentStatus,
|
|
62
|
+
project: file.frontmatter.project as string | undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.logger.info(
|
|
66
|
+
{ filePath, from: previousStatus, to: currentStatus },
|
|
67
|
+
'Status changed'
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// Emit status change event if event bus is available
|
|
71
|
+
if (this.eventBus) {
|
|
72
|
+
this.eventBus.emitEvent(
|
|
73
|
+
'project:updated',
|
|
74
|
+
{
|
|
75
|
+
statusChange,
|
|
76
|
+
filePath,
|
|
77
|
+
project: file.frontmatter.project
|
|
78
|
+
},
|
|
79
|
+
this.name
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.logSuccess(event, { from: previousStatus, to: currentStatus })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Update cached status
|
|
87
|
+
this.previousStatuses.set(filePath, currentStatus)
|
|
88
|
+
} catch (error) {
|
|
89
|
+
this.logError(event, error)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Initialize status tracking for a file
|
|
95
|
+
*/
|
|
96
|
+
async initializeStatus(filePath: string): Promise<void> {
|
|
97
|
+
try {
|
|
98
|
+
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
99
|
+
const status = file.frontmatter.status as string | undefined
|
|
100
|
+
|
|
101
|
+
if (status) {
|
|
102
|
+
this.previousStatuses.set(filePath, status)
|
|
103
|
+
this.logger.debug({ filePath, status }, 'Status initialized')
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
this.logger.warn({ filePath, error }, 'Failed to initialize status')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get cached status for a file
|
|
112
|
+
*/
|
|
113
|
+
getCachedStatus(filePath: string): string | undefined {
|
|
114
|
+
return this.previousStatuses.get(filePath)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Clear status cache
|
|
119
|
+
*/
|
|
120
|
+
clearStatusCache(): void {
|
|
121
|
+
this.previousStatuses.clear()
|
|
122
|
+
this.logger.debug('Status cache cleared')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get all tracked file paths
|
|
127
|
+
*/
|
|
128
|
+
getTrackedFiles(): string[] {
|
|
129
|
+
return Array.from(this.previousStatuses.keys())
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TaskHandler - Detects and processes tasks from progress.md files
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Logger } from 'pino'
|
|
6
|
-
import type { Event, EventType, EventPriority } from '../types'
|
|
7
|
-
import type { VaultReader } from '@/vault'
|
|
8
|
-
import { BaseHandler } from './base-handler'
|
|
9
|
-
import type { EventBus } from '../event-emitter'
|
|
10
|
-
|
|
11
|
-
export interface DetectedTask {
|
|
12
|
-
title: string
|
|
13
|
-
status: string
|
|
14
|
-
description?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class TaskHandler extends BaseHandler {
|
|
18
|
-
name = 'task-handler'
|
|
19
|
-
types: EventType[] = ['file:created', 'file:modified']
|
|
20
|
-
priority: EventPriority = 'normal'
|
|
21
|
-
|
|
22
|
-
private vaultReader: VaultReader
|
|
23
|
-
private eventBus: EventBus | null = null
|
|
24
|
-
|
|
25
|
-
constructor(logger: Logger, vaultReader: VaultReader) {
|
|
26
|
-
super(logger)
|
|
27
|
-
this.initLogger(logger)
|
|
28
|
-
this.vaultReader = vaultReader
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Set the event bus for emitting task events
|
|
33
|
-
*/
|
|
34
|
-
setEventBus(eventBus: EventBus): void {
|
|
35
|
-
this.eventBus = eventBus
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async handle(event: Event): Promise<void> {
|
|
39
|
-
this.logHandling(event)
|
|
40
|
-
|
|
41
|
-
const filePath = event.payload.path as string
|
|
42
|
-
|
|
43
|
-
// Only process progress.md files
|
|
44
|
-
if (!this.shouldHandleFile(filePath, ['progress.md'])) {
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
// Read file
|
|
50
|
-
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
51
|
-
|
|
52
|
-
// Check for task markers in content
|
|
53
|
-
const tasks = this.extractTasks(file.content)
|
|
54
|
-
|
|
55
|
-
if (tasks.length > 0) {
|
|
56
|
-
this.logger.info(
|
|
57
|
-
{ filePath, taskCount: tasks.length },
|
|
58
|
-
'Tasks detected'
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
// Emit task events if event bus is available
|
|
62
|
-
if (this.eventBus) {
|
|
63
|
-
for (const task of tasks) {
|
|
64
|
-
const eventType = this.getTaskEventType(task.status)
|
|
65
|
-
this.eventBus.emitEvent(
|
|
66
|
-
eventType,
|
|
67
|
-
{
|
|
68
|
-
task,
|
|
69
|
-
filePath,
|
|
70
|
-
project: file.frontmatter.project
|
|
71
|
-
},
|
|
72
|
-
this.name
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this.logSuccess(event, { taskCount: tasks.length })
|
|
78
|
-
}
|
|
79
|
-
} catch (error) {
|
|
80
|
-
this.logError(event, error)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Extract tasks from markdown content
|
|
86
|
-
*/
|
|
87
|
-
private extractTasks(content: string): DetectedTask[] {
|
|
88
|
-
const tasks: DetectedTask[] = []
|
|
89
|
-
|
|
90
|
-
// Look for task patterns like:
|
|
91
|
-
// ## Task: [title]
|
|
92
|
-
// Status: [status]
|
|
93
|
-
const taskRegex = /##\s+Task:\s+(.+?)(?:\n|$)/gi
|
|
94
|
-
const statusRegex = /Status:\s+(.+?)(?:\n|$)/i
|
|
95
|
-
|
|
96
|
-
let match
|
|
97
|
-
while ((match = taskRegex.exec(content)) !== null) {
|
|
98
|
-
const title = match[1]?.trim() ?? ''
|
|
99
|
-
if (!title) continue
|
|
100
|
-
|
|
101
|
-
const sectionStart = match.index
|
|
102
|
-
const nextSection = content.indexOf('##', sectionStart + 1)
|
|
103
|
-
const sectionEnd = nextSection === -1 ? content.length : nextSection
|
|
104
|
-
const section = content.slice(sectionStart, sectionEnd)
|
|
105
|
-
|
|
106
|
-
const statusMatch = statusRegex.exec(section)
|
|
107
|
-
const status = statusMatch?.[1]?.trim() ?? 'unknown'
|
|
108
|
-
|
|
109
|
-
tasks.push({
|
|
110
|
-
title,
|
|
111
|
-
status,
|
|
112
|
-
description: section.slice(match[0].length, 100).trim()
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Also look for checkbox-style tasks
|
|
117
|
-
const checkboxTasks = this.extractCheckboxTasks(content)
|
|
118
|
-
tasks.push(...checkboxTasks)
|
|
119
|
-
|
|
120
|
-
return tasks
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Extract checkbox-style tasks
|
|
125
|
-
*/
|
|
126
|
-
private extractCheckboxTasks(content: string): DetectedTask[] {
|
|
127
|
-
const tasks: DetectedTask[] = []
|
|
128
|
-
|
|
129
|
-
// Match: - [ ] Task, - [x] Task, - [>] Task, - [!] Task
|
|
130
|
-
const checkboxRegex = /^[-*]\s+\[([ xX>!])\]\s+(.+)$/gm
|
|
131
|
-
|
|
132
|
-
let match
|
|
133
|
-
while ((match = checkboxRegex.exec(content)) !== null) {
|
|
134
|
-
const statusChar = match[1] ?? ' '
|
|
135
|
-
const title = match[2]?.trim() ?? ''
|
|
136
|
-
if (!title) continue
|
|
137
|
-
|
|
138
|
-
let status: string
|
|
139
|
-
if (statusChar === 'x' || statusChar === 'X') {
|
|
140
|
-
status = 'done'
|
|
141
|
-
} else if (statusChar === '>') {
|
|
142
|
-
status = 'in-progress'
|
|
143
|
-
} else if (statusChar === '!') {
|
|
144
|
-
status = 'blocked'
|
|
145
|
-
} else {
|
|
146
|
-
status = 'todo'
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
tasks.push({ title, status })
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return tasks
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Map task status to event type
|
|
157
|
-
*/
|
|
158
|
-
private getTaskEventType(status: string): EventType {
|
|
159
|
-
const normalizedStatus = status.toLowerCase()
|
|
160
|
-
|
|
161
|
-
if (normalizedStatus.includes('done') || normalizedStatus.includes('complete')) {
|
|
162
|
-
return 'task:completed'
|
|
163
|
-
} else if (normalizedStatus.includes('block')) {
|
|
164
|
-
return 'task:blocked'
|
|
165
|
-
} else if (normalizedStatus.includes('progress') || normalizedStatus.includes('doing')) {
|
|
166
|
-
return 'task:updated'
|
|
167
|
-
} else {
|
|
168
|
-
return 'task:created'
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* TaskHandler - Detects and processes tasks from progress.md files
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Logger } from 'pino'
|
|
6
|
+
import type { Event, EventType, EventPriority } from '../types'
|
|
7
|
+
import type { VaultReader } from '@/vault'
|
|
8
|
+
import { BaseHandler } from './base-handler'
|
|
9
|
+
import type { EventBus } from '../event-emitter'
|
|
10
|
+
|
|
11
|
+
export interface DetectedTask {
|
|
12
|
+
title: string
|
|
13
|
+
status: string
|
|
14
|
+
description?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TaskHandler extends BaseHandler {
|
|
18
|
+
name = 'task-handler'
|
|
19
|
+
types: EventType[] = ['file:created', 'file:modified']
|
|
20
|
+
priority: EventPriority = 'normal'
|
|
21
|
+
|
|
22
|
+
private vaultReader: VaultReader
|
|
23
|
+
private eventBus: EventBus | null = null
|
|
24
|
+
|
|
25
|
+
constructor(logger: Logger, vaultReader: VaultReader) {
|
|
26
|
+
super(logger)
|
|
27
|
+
this.initLogger(logger)
|
|
28
|
+
this.vaultReader = vaultReader
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the event bus for emitting task events
|
|
33
|
+
*/
|
|
34
|
+
setEventBus(eventBus: EventBus): void {
|
|
35
|
+
this.eventBus = eventBus
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async handle(event: Event): Promise<void> {
|
|
39
|
+
this.logHandling(event)
|
|
40
|
+
|
|
41
|
+
const filePath = event.payload.path as string
|
|
42
|
+
|
|
43
|
+
// Only process progress.md files
|
|
44
|
+
if (!this.shouldHandleFile(filePath, ['progress.md'])) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// Read file
|
|
50
|
+
const file = await this.vaultReader.readMarkdownFile(filePath, false)
|
|
51
|
+
|
|
52
|
+
// Check for task markers in content
|
|
53
|
+
const tasks = this.extractTasks(file.content)
|
|
54
|
+
|
|
55
|
+
if (tasks.length > 0) {
|
|
56
|
+
this.logger.info(
|
|
57
|
+
{ filePath, taskCount: tasks.length },
|
|
58
|
+
'Tasks detected'
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
// Emit task events if event bus is available
|
|
62
|
+
if (this.eventBus) {
|
|
63
|
+
for (const task of tasks) {
|
|
64
|
+
const eventType = this.getTaskEventType(task.status)
|
|
65
|
+
this.eventBus.emitEvent(
|
|
66
|
+
eventType,
|
|
67
|
+
{
|
|
68
|
+
task,
|
|
69
|
+
filePath,
|
|
70
|
+
project: file.frontmatter.project
|
|
71
|
+
},
|
|
72
|
+
this.name
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.logSuccess(event, { taskCount: tasks.length })
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
this.logError(event, error)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Extract tasks from markdown content
|
|
86
|
+
*/
|
|
87
|
+
private extractTasks(content: string): DetectedTask[] {
|
|
88
|
+
const tasks: DetectedTask[] = []
|
|
89
|
+
|
|
90
|
+
// Look for task patterns like:
|
|
91
|
+
// ## Task: [title]
|
|
92
|
+
// Status: [status]
|
|
93
|
+
const taskRegex = /##\s+Task:\s+(.+?)(?:\n|$)/gi
|
|
94
|
+
const statusRegex = /Status:\s+(.+?)(?:\n|$)/i
|
|
95
|
+
|
|
96
|
+
let match
|
|
97
|
+
while ((match = taskRegex.exec(content)) !== null) {
|
|
98
|
+
const title = match[1]?.trim() ?? ''
|
|
99
|
+
if (!title) continue
|
|
100
|
+
|
|
101
|
+
const sectionStart = match.index
|
|
102
|
+
const nextSection = content.indexOf('##', sectionStart + 1)
|
|
103
|
+
const sectionEnd = nextSection === -1 ? content.length : nextSection
|
|
104
|
+
const section = content.slice(sectionStart, sectionEnd)
|
|
105
|
+
|
|
106
|
+
const statusMatch = statusRegex.exec(section)
|
|
107
|
+
const status = statusMatch?.[1]?.trim() ?? 'unknown'
|
|
108
|
+
|
|
109
|
+
tasks.push({
|
|
110
|
+
title,
|
|
111
|
+
status,
|
|
112
|
+
description: section.slice(match[0].length, 100).trim()
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Also look for checkbox-style tasks
|
|
117
|
+
const checkboxTasks = this.extractCheckboxTasks(content)
|
|
118
|
+
tasks.push(...checkboxTasks)
|
|
119
|
+
|
|
120
|
+
return tasks
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Extract checkbox-style tasks
|
|
125
|
+
*/
|
|
126
|
+
private extractCheckboxTasks(content: string): DetectedTask[] {
|
|
127
|
+
const tasks: DetectedTask[] = []
|
|
128
|
+
|
|
129
|
+
// Match: - [ ] Task, - [x] Task, - [>] Task, - [!] Task
|
|
130
|
+
const checkboxRegex = /^[-*]\s+\[([ xX>!])\]\s+(.+)$/gm
|
|
131
|
+
|
|
132
|
+
let match
|
|
133
|
+
while ((match = checkboxRegex.exec(content)) !== null) {
|
|
134
|
+
const statusChar = match[1] ?? ' '
|
|
135
|
+
const title = match[2]?.trim() ?? ''
|
|
136
|
+
if (!title) continue
|
|
137
|
+
|
|
138
|
+
let status: string
|
|
139
|
+
if (statusChar === 'x' || statusChar === 'X') {
|
|
140
|
+
status = 'done'
|
|
141
|
+
} else if (statusChar === '>') {
|
|
142
|
+
status = 'in-progress'
|
|
143
|
+
} else if (statusChar === '!') {
|
|
144
|
+
status = 'blocked'
|
|
145
|
+
} else {
|
|
146
|
+
status = 'todo'
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
tasks.push({ title, status })
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return tasks
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Map task status to event type
|
|
157
|
+
*/
|
|
158
|
+
private getTaskEventType(status: string): EventType {
|
|
159
|
+
const normalizedStatus = status.toLowerCase()
|
|
160
|
+
|
|
161
|
+
if (normalizedStatus.includes('done') || normalizedStatus.includes('complete')) {
|
|
162
|
+
return 'task:completed'
|
|
163
|
+
} else if (normalizedStatus.includes('block')) {
|
|
164
|
+
return 'task:blocked'
|
|
165
|
+
} else if (normalizedStatus.includes('progress') || normalizedStatus.includes('doing')) {
|
|
166
|
+
return 'task:updated'
|
|
167
|
+
} else {
|
|
168
|
+
return 'task:created'
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|