claude-memory-layer 1.0.31 → 1.0.32
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 +9 -2
- package/dist/cli/index.js +1 -1
- package/package.json +11 -2
- package/scripts/postinstall-embedding-backend.cjs +16 -12
- package/AGENTS.md +0 -71
- package/CLAUDE.md +0 -30
- package/HANDOFF.md +0 -92
- package/Memo.txt +0 -558
- package/benchmarks/replay/anonymized-real-sessions.json +0 -48
- package/config/kpi-thresholds.json +0 -7
- package/context.md +0 -636
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +0 -627
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +0 -440
- package/docs/MCP_MEMORY_SERVICE_COMPARATIVE_REVIEW.md +0 -271
- package/docs/MEMORY_USEFULNESS_AUDIT.md +0 -371
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +0 -80
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +0 -333
- package/docs/MEMU_ADOPTION.md +0 -40
- package/docs/OPERATIONS.md +0 -18
- package/docs/PRODUCT_VALIDATION_MATRIX.md +0 -82
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +0 -421
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +0 -501
- package/docs/REFACTORING_PLAN_THIN_CORE.md +0 -414
- package/docs/REFERENCE_PROJECT_ANALYSES.md +0 -25
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +0 -452
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +0 -446
- package/docs/architecture/comparison-index.md +0 -47
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +0 -46
- package/plan.md +0 -1642
- package/scripts/build.ts +0 -159
- package/scripts/bump-patch-version.sh +0 -18
- package/scripts/delete-unknown-projects.js +0 -154
- package/scripts/fix-sync-gap.js +0 -32
- package/scripts/generate-session-qrels.ts +0 -126
- package/scripts/heartbeat-memory-orchestrator.sh +0 -28
- package/scripts/replay-retrieval-benchmark.ts +0 -69
- package/scripts/report-sync-gap.js +0 -26
- package/scripts/review-queue-auto-resolve.js +0 -21
- package/scripts/sync-gap-auto-heal.sh +0 -17
- package/spec.md +0 -624
- package/specs/20260207-dashboard-upgrade/context.md +0 -38
- package/specs/20260207-dashboard-upgrade/spec.md +0 -96
- package/specs/citations-system/context.md +0 -243
- package/specs/citations-system/plan.md +0 -495
- package/specs/citations-system/spec.md +0 -371
- package/specs/endless-mode/context.md +0 -305
- package/specs/endless-mode/plan.md +0 -620
- package/specs/endless-mode/spec.md +0 -455
- package/specs/entity-edge-model/context.md +0 -401
- package/specs/entity-edge-model/plan.md +0 -459
- package/specs/entity-edge-model/spec.md +0 -391
- package/specs/evidence-aligner-v2/context.md +0 -401
- package/specs/evidence-aligner-v2/plan.md +0 -303
- package/specs/evidence-aligner-v2/spec.md +0 -312
- package/specs/mcp-desktop-integration/context.md +0 -278
- package/specs/mcp-desktop-integration/plan.md +0 -550
- package/specs/mcp-desktop-integration/spec.md +0 -494
- package/specs/memory-utilization-improvements/context.md +0 -145
- package/specs/memory-utilization-improvements/plan.md +0 -361
- package/specs/memory-utilization-improvements/spec.md +0 -361
- package/specs/post-tool-use-hook/context.md +0 -319
- package/specs/post-tool-use-hook/plan.md +0 -469
- package/specs/post-tool-use-hook/spec.md +0 -364
- package/specs/private-tags/context.md +0 -288
- package/specs/private-tags/plan.md +0 -412
- package/specs/private-tags/spec.md +0 -345
- package/specs/progressive-disclosure/context.md +0 -346
- package/specs/progressive-disclosure/plan.md +0 -663
- package/specs/progressive-disclosure/spec.md +0 -415
- package/specs/selective-tool-observation/context.md +0 -100
- package/specs/selective-tool-observation/plan.md +0 -158
- package/specs/selective-tool-observation/spec.md +0 -127
- package/specs/task-entity-system/context.md +0 -297
- package/specs/task-entity-system/plan.md +0 -301
- package/specs/task-entity-system/spec.md +0 -314
- package/specs/thin-core-refactor/context.md +0 -275
- package/specs/thin-core-refactor/plan.md +0 -536
- package/specs/thin-core-refactor/spec.md +0 -465
- package/specs/vector-outbox-v2/context.md +0 -470
- package/specs/vector-outbox-v2/plan.md +0 -562
- package/specs/vector-outbox-v2/spec.md +0 -466
- package/specs/web-viewer-ui/context.md +0 -384
- package/specs/web-viewer-ui/plan.md +0 -797
- package/specs/web-viewer-ui/spec.md +0 -516
- package/src/adapters/claude/capture/index.ts +0 -3
- package/src/adapters/claude/context/index.ts +0 -3
- package/src/adapters/claude/hooks/index.ts +0 -21
- package/src/adapters/claude/hooks/post-tool-use.ts +0 -239
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +0 -104
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +0 -209
- package/src/adapters/claude/hooks/semantic-daemon.ts +0 -283
- package/src/adapters/claude/hooks/session-end.ts +0 -59
- package/src/adapters/claude/hooks/session-start.ts +0 -73
- package/src/adapters/claude/hooks/stop.ts +0 -128
- package/src/adapters/claude/hooks/user-prompt-submit.ts +0 -361
- package/src/adapters/claude/index.ts +0 -4
- package/src/adapters/claude/transcript/index.ts +0 -4
- package/src/adapters/claude/transcript/transcript-reader.ts +0 -57
- package/src/adapters/claude/transcript/turn-reconstructor.ts +0 -65
- package/src/apps/cli/claude-settings-hooks.ts +0 -138
- package/src/apps/cli/codex-import-runner.ts +0 -125
- package/src/apps/cli/codex-validation-output.ts +0 -95
- package/src/apps/cli/hermes-import-runner.ts +0 -130
- package/src/apps/cli/hermes-validation-output.ts +0 -91
- package/src/apps/cli/index.ts +0 -1735
- package/src/apps/cli/mcp-install.ts +0 -106
- package/src/apps/cli/retrieval-disclosure-output.ts +0 -196
- package/src/apps/dashboard/assets/js/bootstrap.js +0 -244
- package/src/apps/dashboard/assets/js/chat.js +0 -373
- package/src/apps/dashboard/assets/js/disclosure.js +0 -232
- package/src/apps/dashboard/assets/js/modals.js +0 -298
- package/src/apps/dashboard/assets/js/overview.js +0 -655
- package/src/apps/dashboard/assets/js/state.js +0 -72
- package/src/apps/dashboard/assets/js/views.js +0 -468
- package/src/apps/dashboard/index.html +0 -543
- package/src/apps/dashboard/index.ts +0 -3
- package/src/apps/dashboard/style.css +0 -1750
- package/src/apps/index.ts +0 -5
- package/src/apps/server/api/chat.ts +0 -244
- package/src/apps/server/api/citations.ts +0 -105
- package/src/apps/server/api/events.ts +0 -137
- package/src/apps/server/api/health.ts +0 -53
- package/src/apps/server/api/index.ts +0 -26
- package/src/apps/server/api/projects.ts +0 -74
- package/src/apps/server/api/search.ts +0 -184
- package/src/apps/server/api/sessions.ts +0 -115
- package/src/apps/server/api/stats.ts +0 -723
- package/src/apps/server/api/turns.ts +0 -143
- package/src/apps/server/api/utils.ts +0 -65
- package/src/apps/server/index.ts +0 -111
- package/src/cli/index.ts +0 -3
- package/src/cli/retrieval-disclosure-output.ts +0 -2
- package/src/compat/index.ts +0 -5
- package/src/core/canonical-key.ts +0 -186
- package/src/core/citation-generator.ts +0 -63
- package/src/core/consolidated-store.ts +0 -356
- package/src/core/consolidation-worker.ts +0 -493
- package/src/core/context-formatter.ts +0 -276
- package/src/core/continuity-manager.ts +0 -341
- package/src/core/db-wrapper.ts +0 -64
- package/src/core/derive/fact-deriver.ts +0 -170
- package/src/core/derive/index.ts +0 -2
- package/src/core/derive/summary-deriver.ts +0 -76
- package/src/core/edge-repo.ts +0 -333
- package/src/core/embedder.ts +0 -4
- package/src/core/engine/embedding-maintenance-service.ts +0 -187
- package/src/core/engine/endless-memory-services.ts +0 -4
- package/src/core/engine/index.ts +0 -19
- package/src/core/engine/memory-engine-services.ts +0 -170
- package/src/core/engine/memory-ingest-service.ts +0 -317
- package/src/core/engine/memory-query-service.ts +0 -173
- package/src/core/engine/memory-runtime-service.ts +0 -162
- package/src/core/engine/memory-service-composition.ts +0 -231
- package/src/core/engine/retrieval-analytics-service.ts +0 -181
- package/src/core/engine/retrieval-disclosure-service.ts +0 -420
- package/src/core/engine/retrieval-orchestrator.ts +0 -377
- package/src/core/engine/retrieval-services.ts +0 -176
- package/src/core/engine/shared-memory-services.ts +0 -4
- package/src/core/entity-repo.ts +0 -349
- package/src/core/event-store.ts +0 -779
- package/src/core/evidence-aligner.ts +0 -635
- package/src/core/external-market-context.ts +0 -582
- package/src/core/graduation-worker.ts +0 -171
- package/src/core/graduation.ts +0 -377
- package/src/core/index.ts +0 -64
- package/src/core/ingest-interceptor.ts +0 -80
- package/src/core/markdown-mirror.ts +0 -70
- package/src/core/matcher.ts +0 -208
- package/src/core/md-mirror.ts +0 -92
- package/src/core/metadata-extractor.ts +0 -203
- package/src/core/model/memory-fact.ts +0 -30
- package/src/core/model/memory-rule.ts +0 -14
- package/src/core/model/memory-summary.ts +0 -21
- package/src/core/model/raw-event.ts +0 -28
- package/src/core/model/retrieval-result.ts +0 -35
- package/src/core/mongo-sync-config.ts +0 -165
- package/src/core/mongo-sync-worker.ts +0 -381
- package/src/core/privacy/filter.ts +0 -190
- package/src/core/privacy/index.ts +0 -20
- package/src/core/privacy/tag-parser.ts +0 -145
- package/src/core/product-validation-matrix.ts +0 -314
- package/src/core/progressive-retriever.ts +0 -414
- package/src/core/registry/project-path.ts +0 -54
- package/src/core/registry/session-registry.ts +0 -69
- package/src/core/replay-evaluator.ts +0 -625
- package/src/core/retrieval-benchmark.ts +0 -117
- package/src/core/retrieval-quality.ts +0 -109
- package/src/core/retriever.ts +0 -800
- package/src/core/session-qrels.ts +0 -360
- package/src/core/shared-event-store.ts +0 -114
- package/src/core/shared-promoter.ts +0 -249
- package/src/core/shared-store.ts +0 -289
- package/src/core/shared-vector-store.ts +0 -203
- package/src/core/sqlite-event-store.ts +0 -1846
- package/src/core/sqlite-wrapper.ts +0 -116
- package/src/core/sync-worker.ts +0 -228
- package/src/core/tag-taxonomy.ts +0 -51
- package/src/core/task/blocker-resolver.ts +0 -333
- package/src/core/task/index.ts +0 -9
- package/src/core/task/task-matcher.ts +0 -240
- package/src/core/task/task-projector.ts +0 -358
- package/src/core/task/task-resolver.ts +0 -421
- package/src/core/turn-state.ts +0 -207
- package/src/core/types.ts +0 -952
- package/src/core/vector-outbox.ts +0 -299
- package/src/core/vector-store.ts +0 -231
- package/src/core/vector-worker.ts +0 -521
- package/src/core/working-set-store.ts +0 -257
- package/src/extensions/endless-memory/endless-memory-services.ts +0 -350
- package/src/extensions/endless-memory/index.ts +0 -1
- package/src/extensions/index.ts +0 -5
- package/src/extensions/mcp/handlers.ts +0 -960
- package/src/extensions/mcp/index.ts +0 -48
- package/src/extensions/mcp/tools.ts +0 -252
- package/src/extensions/shared-memory/index.ts +0 -1
- package/src/extensions/shared-memory/shared-memory-services.ts +0 -211
- package/src/extensions/vector/embedder.ts +0 -234
- package/src/extensions/vector/index.ts +0 -1
- package/src/hooks/post-tool-use.ts +0 -9
- package/src/hooks/semantic-daemon-client.ts +0 -1
- package/src/hooks/semantic-daemon.ts +0 -11
- package/src/hooks/session-end.ts +0 -9
- package/src/hooks/session-start.ts +0 -9
- package/src/hooks/stop.ts +0 -9
- package/src/hooks/user-prompt-submit.ts +0 -9
- package/src/index.ts +0 -13
- package/src/mcp/handlers.ts +0 -2
- package/src/mcp/index.ts +0 -4
- package/src/mcp/tools.ts +0 -2
- package/src/server/api/chat.ts +0 -2
- package/src/server/api/citations.ts +0 -2
- package/src/server/api/events.ts +0 -2
- package/src/server/api/health.ts +0 -2
- package/src/server/api/index.ts +0 -2
- package/src/server/api/projects.ts +0 -2
- package/src/server/api/search.ts +0 -2
- package/src/server/api/sessions.ts +0 -2
- package/src/server/api/stats.ts +0 -2
- package/src/server/api/turns.ts +0 -2
- package/src/server/api/utils.ts +0 -2
- package/src/server/index.ts +0 -2
- package/src/services/bootstrap-organizer.ts +0 -463
- package/src/services/codex-session-history-importer.ts +0 -966
- package/src/services/hermes-session-history-importer.ts +0 -733
- package/src/services/memory-service-config.ts +0 -36
- package/src/services/memory-service-registry.ts +0 -150
- package/src/services/memory-service.ts +0 -688
- package/src/services/session-history-importer.ts +0 -629
- package/tests/README.md +0 -23
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +0 -54
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +0 -98
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +0 -99
- package/tests/apps/app-layer-boundary.test.ts +0 -48
- package/tests/apps/claude-settings-hooks.test.ts +0 -107
- package/tests/apps/cli-disclosure-output.test.ts +0 -212
- package/tests/apps/codex-import-runner.test.ts +0 -99
- package/tests/apps/codex-validation-output.test.ts +0 -100
- package/tests/apps/hermes-import-runner.test.ts +0 -99
- package/tests/apps/mcp-install-command.test.ts +0 -59
- package/tests/apps/package-build-entrypoints.test.ts +0 -30
- package/tests/apps/postinstall-embedding-backend.test.ts +0 -185
- package/tests/apps/search-api-disclosure.test.ts +0 -162
- package/tests/apps/stats-api-lightweight.test.ts +0 -67
- package/tests/apps/ui-disclosure-output.test.ts +0 -140
- package/tests/core/bootstrap-organizer.test.ts +0 -111
- package/tests/core/canonical-key.test.ts +0 -101
- package/tests/core/codex-session-history-importer-validation.test.ts +0 -185
- package/tests/core/consolidation-worker.test.ts +0 -75
- package/tests/core/embedding-maintenance-service.test.ts +0 -282
- package/tests/core/evidence-aligner.test.ts +0 -152
- package/tests/core/external-market-context.test.ts +0 -209
- package/tests/core/fact-deriver.test.ts +0 -79
- package/tests/core/hermes-session-history-importer-validation.test.ts +0 -609
- package/tests/core/ingest-interceptor.test.ts +0 -38
- package/tests/core/markdown-mirror.test.ts +0 -85
- package/tests/core/matcher.test.ts +0 -112
- package/tests/core/md-mirror.test.ts +0 -50
- package/tests/core/memory-engine-services.test.ts +0 -240
- package/tests/core/memory-ingest-service.test.ts +0 -296
- package/tests/core/memory-query-service.test.ts +0 -129
- package/tests/core/memory-runtime-service.test.ts +0 -201
- package/tests/core/memory-service-composition.test.ts +0 -192
- package/tests/core/memory-service-config.test.ts +0 -41
- package/tests/core/memory-service-facade.test.ts +0 -30
- package/tests/core/memory-service-registry.test.ts +0 -206
- package/tests/core/product-validation-matrix.test.ts +0 -61
- package/tests/core/project-registry.test.ts +0 -78
- package/tests/core/replay-evaluator.test.ts +0 -181
- package/tests/core/retrieval-analytics-service.test.ts +0 -210
- package/tests/core/retrieval-benchmark.test.ts +0 -93
- package/tests/core/retrieval-disclosure-service.test.ts +0 -264
- package/tests/core/retrieval-orchestrator.test.ts +0 -403
- package/tests/core/retrieval-quality.test.ts +0 -31
- package/tests/core/retrieval-services.test.ts +0 -185
- package/tests/core/retriever-fallback-chain.test.ts +0 -223
- package/tests/core/retriever-strategy-scope.test.ts +0 -164
- package/tests/core/retriever.memu-adoption.test.ts +0 -122
- package/tests/core/session-history-importer-filter.test.ts +0 -78
- package/tests/core/session-qrels.test.ts +0 -250
- package/tests/core/sqlite-event-store-replication.test.ts +0 -127
- package/tests/core/summary-deriver.test.ts +0 -66
- package/tests/extensions/embedder-warning-suppression.test.ts +0 -84
- package/tests/extensions/endless-memory-extension-boundary.test.ts +0 -17
- package/tests/extensions/endless-memory-services.test.ts +0 -325
- package/tests/extensions/mcp-context-tools.test.ts +0 -905
- package/tests/extensions/mcp-extension-boundary.test.ts +0 -21
- package/tests/extensions/mcp-package-build.test.ts +0 -22
- package/tests/extensions/mcp-project-aware-tools.test.ts +0 -102
- package/tests/extensions/shared-memory-extension-boundary.test.ts +0 -24
- package/tests/extensions/shared-memory-services.test.ts +0 -309
- package/tests/extensions/vector-extension-boundary.test.ts +0 -21
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -15
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Consolidation Worker
|
|
3
|
-
* Periodically consolidates working set into long-term memory
|
|
4
|
-
* Biomimetic: Simulates memory consolidation during sleep/idle periods
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type {
|
|
8
|
-
EndlessModeConfig,
|
|
9
|
-
MemoryEvent,
|
|
10
|
-
EventGroup,
|
|
11
|
-
WorkingSet,
|
|
12
|
-
ConsolidationCostQualityReport
|
|
13
|
-
} from './types.js';
|
|
14
|
-
import { WorkingSetStore } from './working-set-store.js';
|
|
15
|
-
import { ConsolidatedStore } from './consolidated-store.js';
|
|
16
|
-
|
|
17
|
-
export class ConsolidationWorker {
|
|
18
|
-
private running = false;
|
|
19
|
-
private timeout: NodeJS.Timeout | null = null;
|
|
20
|
-
private lastActivity: Date = new Date();
|
|
21
|
-
|
|
22
|
-
constructor(
|
|
23
|
-
private workingSetStore: WorkingSetStore,
|
|
24
|
-
private consolidatedStore: ConsolidatedStore,
|
|
25
|
-
private config: EndlessModeConfig
|
|
26
|
-
) {}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Start the consolidation worker
|
|
30
|
-
*/
|
|
31
|
-
start(): void {
|
|
32
|
-
if (this.running) return;
|
|
33
|
-
this.running = true;
|
|
34
|
-
this.scheduleNext();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Stop the consolidation worker
|
|
39
|
-
*/
|
|
40
|
-
stop(): void {
|
|
41
|
-
this.running = false;
|
|
42
|
-
if (this.timeout) {
|
|
43
|
-
clearTimeout(this.timeout);
|
|
44
|
-
this.timeout = null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Record activity (resets idle timer)
|
|
50
|
-
*/
|
|
51
|
-
recordActivity(): void {
|
|
52
|
-
this.lastActivity = new Date();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Check if currently running
|
|
57
|
-
*/
|
|
58
|
-
isRunning(): boolean {
|
|
59
|
-
return this.running;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Force a consolidation run (manual trigger)
|
|
64
|
-
*/
|
|
65
|
-
async forceRun(): Promise<number> {
|
|
66
|
-
const out = await this.consolidateWithReport();
|
|
67
|
-
return out.consolidatedCount;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Force a consolidation run and return metrics report
|
|
72
|
-
*/
|
|
73
|
-
async forceRunWithReport(): Promise<{
|
|
74
|
-
consolidatedCount: number;
|
|
75
|
-
promotedRuleCount: number;
|
|
76
|
-
report: ConsolidationCostQualityReport;
|
|
77
|
-
}> {
|
|
78
|
-
return this.consolidateWithReport();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Schedule the next consolidation check
|
|
83
|
-
*/
|
|
84
|
-
private scheduleNext(): void {
|
|
85
|
-
if (!this.running) return;
|
|
86
|
-
|
|
87
|
-
this.timeout = setTimeout(
|
|
88
|
-
() => this.run(),
|
|
89
|
-
this.config.consolidation.triggerIntervalMs
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Run consolidation check
|
|
95
|
-
*/
|
|
96
|
-
private async run(): Promise<void> {
|
|
97
|
-
if (!this.running) return;
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await this.checkAndConsolidate();
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.error('Consolidation error:', error);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
this.scheduleNext();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Check conditions and consolidate if needed
|
|
110
|
-
*/
|
|
111
|
-
private async checkAndConsolidate(): Promise<void> {
|
|
112
|
-
const workingSet = await this.workingSetStore.get();
|
|
113
|
-
|
|
114
|
-
if (!this.shouldConsolidate(workingSet)) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
await this.consolidate();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Perform consolidation
|
|
123
|
-
*/
|
|
124
|
-
private async consolidate(): Promise<number> {
|
|
125
|
-
const out = await this.consolidateWithReport();
|
|
126
|
-
return out.consolidatedCount;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private async consolidateWithReport(): Promise<{
|
|
130
|
-
consolidatedCount: number;
|
|
131
|
-
promotedRuleCount: number;
|
|
132
|
-
report: ConsolidationCostQualityReport;
|
|
133
|
-
}> {
|
|
134
|
-
const workingSet = await this.workingSetStore.get();
|
|
135
|
-
|
|
136
|
-
if (workingSet.recentEvents.length < 3) {
|
|
137
|
-
return {
|
|
138
|
-
consolidatedCount: 0,
|
|
139
|
-
promotedRuleCount: 0,
|
|
140
|
-
report: this.buildCostQualityReport(workingSet.recentEvents, [], 0)
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Group events by topic
|
|
145
|
-
const groups = this.groupByTopic(workingSet.recentEvents);
|
|
146
|
-
let consolidatedCount = 0;
|
|
147
|
-
const createdMemoryIds: string[] = [];
|
|
148
|
-
|
|
149
|
-
for (const group of groups) {
|
|
150
|
-
// Require minimum 3 events per group
|
|
151
|
-
if (group.events.length < 3) continue;
|
|
152
|
-
|
|
153
|
-
// Check if already consolidated
|
|
154
|
-
const eventIds = group.events.map(e => e.id);
|
|
155
|
-
const alreadyConsolidated = await this.consolidatedStore.isAlreadyConsolidated(eventIds);
|
|
156
|
-
if (alreadyConsolidated) continue;
|
|
157
|
-
|
|
158
|
-
// Generate summary
|
|
159
|
-
const summary = await this.summarize(group);
|
|
160
|
-
|
|
161
|
-
// Create consolidated memory
|
|
162
|
-
const memoryId = await this.consolidatedStore.create({
|
|
163
|
-
summary,
|
|
164
|
-
topics: group.topics,
|
|
165
|
-
sourceEvents: eventIds,
|
|
166
|
-
confidence: this.calculateConfidence(group)
|
|
167
|
-
});
|
|
168
|
-
createdMemoryIds.push(memoryId);
|
|
169
|
-
consolidatedCount++;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const promotedRuleCount = await this.promoteStableSummariesToRules(createdMemoryIds);
|
|
173
|
-
|
|
174
|
-
// Prune consolidated events from working set
|
|
175
|
-
if (consolidatedCount > 0) {
|
|
176
|
-
const consolidatedEventIds = groups
|
|
177
|
-
.filter(g => g.events.length >= 3)
|
|
178
|
-
.flatMap(g => g.events.map(e => e.id));
|
|
179
|
-
|
|
180
|
-
// Only prune old events (keep recent for context)
|
|
181
|
-
const oldEventIds = consolidatedEventIds.filter(id => {
|
|
182
|
-
const event = workingSet.recentEvents.find(e => e.id === id);
|
|
183
|
-
if (!event) return false;
|
|
184
|
-
const ageHours = (Date.now() - event.timestamp.getTime()) / (1000 * 60 * 60);
|
|
185
|
-
return ageHours > this.config.workingSet.timeWindowHours / 2;
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
if (oldEventIds.length > 0) {
|
|
189
|
-
await this.workingSetStore.prune(oldEventIds);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const report = this.buildCostQualityReport(workingSet.recentEvents, groups, consolidatedCount);
|
|
194
|
-
return { consolidatedCount, promotedRuleCount, report };
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private async promoteStableSummariesToRules(memoryIds: string[]): Promise<number> {
|
|
198
|
-
let promoted = 0;
|
|
199
|
-
|
|
200
|
-
for (const memoryId of memoryIds) {
|
|
201
|
-
const memory = await this.consolidatedStore.get(memoryId);
|
|
202
|
-
if (!memory) continue;
|
|
203
|
-
if (memory.confidence < 0.55) continue;
|
|
204
|
-
if (memory.sourceEvents.length < 4) continue;
|
|
205
|
-
|
|
206
|
-
const exists = await this.consolidatedStore.hasRuleForSourceMemory(memoryId);
|
|
207
|
-
if (exists) continue;
|
|
208
|
-
|
|
209
|
-
const rule = this.buildRuleFromSummary(memory.summary, memory.topics);
|
|
210
|
-
if (!rule) continue;
|
|
211
|
-
|
|
212
|
-
await this.consolidatedStore.createRule({
|
|
213
|
-
rule,
|
|
214
|
-
topics: memory.topics,
|
|
215
|
-
sourceMemoryIds: [memory.memoryId],
|
|
216
|
-
sourceEvents: memory.sourceEvents,
|
|
217
|
-
confidence: Math.min(1, memory.confidence + 0.08)
|
|
218
|
-
});
|
|
219
|
-
promoted++;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return promoted;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private buildRuleFromSummary(summary: string, topics: string[]): string | null {
|
|
226
|
-
const lines = summary
|
|
227
|
-
.split(/\r?\n/)
|
|
228
|
-
.map((l) => l.trim())
|
|
229
|
-
.filter(Boolean)
|
|
230
|
-
.filter((l) => !l.toLowerCase().startsWith('topics:'));
|
|
231
|
-
|
|
232
|
-
const bullet = lines.find((l) => l.startsWith('- '))?.replace(/^-\s*/, '');
|
|
233
|
-
const seed = bullet || lines[0];
|
|
234
|
-
if (!seed || seed.length < 8) return null;
|
|
235
|
-
|
|
236
|
-
const topicPrefix = topics.length > 0 ? `[${topics.slice(0, 2).join(', ')}] ` : '';
|
|
237
|
-
return `${topicPrefix}${seed}`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
private buildCostQualityReport(
|
|
241
|
-
events: MemoryEvent[],
|
|
242
|
-
groups: EventGroup[],
|
|
243
|
-
consolidatedCount: number
|
|
244
|
-
): ConsolidationCostQualityReport {
|
|
245
|
-
const beforeTokenEstimate = events.reduce((acc, e) => acc + this.estimateTokens(e.content), 0);
|
|
246
|
-
|
|
247
|
-
const afterSummaries = groups
|
|
248
|
-
.filter((g) => g.events.length >= 3)
|
|
249
|
-
.slice(0, Math.max(consolidatedCount, 1));
|
|
250
|
-
|
|
251
|
-
const afterTokenEstimate = afterSummaries.length > 0
|
|
252
|
-
? afterSummaries.reduce((acc, g) => acc + this.estimateTokens(this.ruleBasedSummary(g)), 0)
|
|
253
|
-
: beforeTokenEstimate;
|
|
254
|
-
|
|
255
|
-
const reductionRatio = beforeTokenEstimate > 0
|
|
256
|
-
? Math.max(0, (beforeTokenEstimate - afterTokenEstimate) / beforeTokenEstimate)
|
|
257
|
-
: 0;
|
|
258
|
-
|
|
259
|
-
const qualityGuardPassed = consolidatedCount === 0
|
|
260
|
-
? true
|
|
261
|
-
: groups.filter((g) => g.events.length >= 3).every((g) => this.calculateConfidence(g) >= 0.55);
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
beforeTokenEstimate,
|
|
265
|
-
afterTokenEstimate,
|
|
266
|
-
reductionRatio,
|
|
267
|
-
qualityGuardPassed,
|
|
268
|
-
details: `groups=${groups.length}, consolidated=${consolidatedCount}`
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
private estimateTokens(text: string): number {
|
|
273
|
-
return Math.ceil((text || '').length / 4);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Check if consolidation should run
|
|
278
|
-
*/
|
|
279
|
-
private shouldConsolidate(workingSet: WorkingSet): boolean {
|
|
280
|
-
// Check event count trigger
|
|
281
|
-
if (workingSet.recentEvents.length >= this.config.consolidation.triggerEventCount) {
|
|
282
|
-
return true;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Check idle time trigger
|
|
286
|
-
const idleTime = Date.now() - this.lastActivity.getTime();
|
|
287
|
-
if (idleTime >= this.config.consolidation.triggerIdleMs) {
|
|
288
|
-
return true;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return false;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Group events by topic using simple keyword extraction
|
|
296
|
-
*/
|
|
297
|
-
private groupByTopic(events: MemoryEvent[]): EventGroup[] {
|
|
298
|
-
const groups = new Map<string, EventGroup>();
|
|
299
|
-
|
|
300
|
-
for (const event of events) {
|
|
301
|
-
const topics = this.extractTopics(event.content);
|
|
302
|
-
|
|
303
|
-
for (const topic of topics) {
|
|
304
|
-
if (!groups.has(topic)) {
|
|
305
|
-
groups.set(topic, { topics: [topic], events: [] });
|
|
306
|
-
}
|
|
307
|
-
const group = groups.get(topic)!;
|
|
308
|
-
if (!group.events.find(e => e.id === event.id)) {
|
|
309
|
-
group.events.push(event);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Merge groups with overlapping events
|
|
315
|
-
const mergedGroups = this.mergeOverlappingGroups(Array.from(groups.values()));
|
|
316
|
-
|
|
317
|
-
return mergedGroups;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Extract topics from content using simple keyword extraction
|
|
322
|
-
*/
|
|
323
|
-
private extractTopics(content: string): string[] {
|
|
324
|
-
const topics: string[] = [];
|
|
325
|
-
|
|
326
|
-
// Extract code-related keywords
|
|
327
|
-
const codePatterns = [
|
|
328
|
-
/\b(function|class|interface|type|const|let|var)\s+(\w+)/gi,
|
|
329
|
-
/\b(import|export)\s+.*?from\s+['"]([^'"]+)['"]/gi,
|
|
330
|
-
/\bfile[:\s]+([^\s,]+)/gi
|
|
331
|
-
];
|
|
332
|
-
|
|
333
|
-
for (const pattern of codePatterns) {
|
|
334
|
-
let match;
|
|
335
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
336
|
-
const keyword = match[2] || match[1];
|
|
337
|
-
if (keyword && keyword.length > 2) {
|
|
338
|
-
topics.push(keyword.toLowerCase());
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Extract common programming terms
|
|
344
|
-
const commonTerms = [
|
|
345
|
-
'bug', 'fix', 'error', 'issue', 'feature',
|
|
346
|
-
'test', 'refactor', 'implement', 'add', 'remove',
|
|
347
|
-
'update', 'change', 'modify', 'create', 'delete'
|
|
348
|
-
];
|
|
349
|
-
|
|
350
|
-
const contentLower = content.toLowerCase();
|
|
351
|
-
for (const term of commonTerms) {
|
|
352
|
-
if (contentLower.includes(term)) {
|
|
353
|
-
topics.push(term);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return [...new Set(topics)].slice(0, 5); // Limit to 5 topics
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Merge groups that have significant event overlap
|
|
362
|
-
*/
|
|
363
|
-
private mergeOverlappingGroups(groups: EventGroup[]): EventGroup[] {
|
|
364
|
-
const merged: EventGroup[] = [];
|
|
365
|
-
|
|
366
|
-
for (const group of groups) {
|
|
367
|
-
let foundMerge = false;
|
|
368
|
-
|
|
369
|
-
for (const existing of merged) {
|
|
370
|
-
const overlap = group.events.filter(e =>
|
|
371
|
-
existing.events.some(ex => ex.id === e.id)
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
// If > 50% overlap, merge
|
|
375
|
-
if (overlap.length > group.events.length / 2) {
|
|
376
|
-
existing.topics = [...new Set([...existing.topics, ...group.topics])];
|
|
377
|
-
for (const event of group.events) {
|
|
378
|
-
if (!existing.events.find(e => e.id === event.id)) {
|
|
379
|
-
existing.events.push(event);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
foundMerge = true;
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (!foundMerge) {
|
|
388
|
-
merged.push(group);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
return merged;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Generate summary for a group of events
|
|
397
|
-
* Rule-based extraction (no LLM by default)
|
|
398
|
-
*/
|
|
399
|
-
private async summarize(group: EventGroup): Promise<string> {
|
|
400
|
-
if (this.config.consolidation.useLLMSummarization) {
|
|
401
|
-
// Future: LLM-based summarization
|
|
402
|
-
return this.ruleBasedSummary(group);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
return this.ruleBasedSummary(group);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Rule-based summary generation
|
|
410
|
-
*/
|
|
411
|
-
private ruleBasedSummary(group: EventGroup): string {
|
|
412
|
-
const keyPoints: string[] = [];
|
|
413
|
-
|
|
414
|
-
for (const event of group.events.slice(0, 10)) {
|
|
415
|
-
const keyPoint = this.extractKeyPoint(event.content);
|
|
416
|
-
if (keyPoint) {
|
|
417
|
-
keyPoints.push(keyPoint);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const topicsStr = group.topics.slice(0, 3).join(', ');
|
|
422
|
-
const summary = [
|
|
423
|
-
`Topics: ${topicsStr}`,
|
|
424
|
-
'',
|
|
425
|
-
'Key points:',
|
|
426
|
-
...keyPoints.map(kp => `- ${kp}`)
|
|
427
|
-
].join('\n');
|
|
428
|
-
|
|
429
|
-
return summary;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Extract key point from content
|
|
434
|
-
*/
|
|
435
|
-
private extractKeyPoint(content: string): string | null {
|
|
436
|
-
// Get first meaningful sentence
|
|
437
|
-
const sentences = content.split(/[.!?\n]+/).filter(s => s.trim().length > 10);
|
|
438
|
-
if (sentences.length === 0) return null;
|
|
439
|
-
|
|
440
|
-
const firstSentence = sentences[0].trim();
|
|
441
|
-
|
|
442
|
-
// Truncate if too long
|
|
443
|
-
if (firstSentence.length > 100) {
|
|
444
|
-
return firstSentence.slice(0, 100) + '...';
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
return firstSentence;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Calculate confidence score for a group
|
|
452
|
-
*/
|
|
453
|
-
private calculateConfidence(group: EventGroup): number {
|
|
454
|
-
// Factor 1: Event count (more events = higher confidence)
|
|
455
|
-
const eventScore = Math.min(group.events.length / 10, 1);
|
|
456
|
-
|
|
457
|
-
// Factor 2: Time proximity (events closer together = higher confidence)
|
|
458
|
-
const timeScore = this.calculateTimeProximity(group.events);
|
|
459
|
-
|
|
460
|
-
// Factor 3: Topic consistency (fewer topics per event = higher confidence)
|
|
461
|
-
const topicScore = Math.min(3 / group.topics.length, 1);
|
|
462
|
-
|
|
463
|
-
return (eventScore * 0.4 + timeScore * 0.4 + topicScore * 0.2);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Calculate time proximity score
|
|
468
|
-
*/
|
|
469
|
-
private calculateTimeProximity(events: MemoryEvent[]): number {
|
|
470
|
-
if (events.length < 2) return 1;
|
|
471
|
-
|
|
472
|
-
const timestamps = events.map(e => e.timestamp.getTime()).sort((a, b) => a - b);
|
|
473
|
-
const timeSpan = timestamps[timestamps.length - 1] - timestamps[0];
|
|
474
|
-
|
|
475
|
-
// Score based on average time between events
|
|
476
|
-
const avgGap = timeSpan / (events.length - 1);
|
|
477
|
-
const hourInMs = 60 * 60 * 1000;
|
|
478
|
-
|
|
479
|
-
// Within 1 hour average = score 1, 24 hours = score 0.5, etc.
|
|
480
|
-
return Math.max(0, 1 - (avgGap / (24 * hourInMs)));
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* Create a Consolidation Worker instance
|
|
486
|
-
*/
|
|
487
|
-
export function createConsolidationWorker(
|
|
488
|
-
workingSetStore: WorkingSetStore,
|
|
489
|
-
consolidatedStore: ConsolidatedStore,
|
|
490
|
-
config: EndlessModeConfig
|
|
491
|
-
): ConsolidationWorker {
|
|
492
|
-
return new ConsolidationWorker(workingSetStore, consolidatedStore, config);
|
|
493
|
-
}
|