autosnippet 3.3.7 → 3.3.8
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 +1 -0
- package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
- package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
- package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.js +7 -4
- package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
- package/dist/lib/agent/core/LoopContext.d.ts +1 -0
- package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
- package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
- package/dist/lib/agent/memory/ActiveContext.js +0 -2
- package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
- package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
- package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
- package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
- package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
- package/dist/lib/agent/memory/MemoryStore.js +196 -261
- package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
- package/dist/lib/agent/memory/PersistentMemory.js +4 -5
- package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
- package/dist/lib/agent/memory/SessionStore.js +0 -2
- package/dist/lib/agent/tools/ast-graph.js +21 -19
- package/dist/lib/agent/tools/infrastructure.js +3 -2
- package/dist/lib/agent/tools/project-access.d.ts +2 -2
- package/dist/lib/agent/tools/project-access.js +5 -4
- package/dist/lib/bootstrap.js +2 -1
- package/dist/lib/cli/AiScanService.js +4 -17
- package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
- package/dist/lib/cli/KnowledgeSyncService.js +23 -51
- package/dist/lib/core/ast/ProjectGraph.js +5 -27
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
- package/dist/lib/domain/dimension/DimensionSop.js +44 -33
- package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
- package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
- package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
- package/dist/lib/domain/knowledge/index.d.ts +2 -1
- package/dist/lib/domain/knowledge/index.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
- package/dist/lib/external/mcp/handlers/guard.js +15 -24
- package/dist/lib/external/mcp/handlers/panorama.js +9 -9
- package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
- package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
- package/dist/lib/external/mcp/handlers/search.js +3 -1
- package/dist/lib/external/mcp/handlers/skill.js +4 -4
- package/dist/lib/external/mcp/handlers/structure.js +8 -12
- package/dist/lib/external/mcp/handlers/system.js +10 -34
- package/dist/lib/http/routes/ai.js +11 -13
- package/dist/lib/http/routes/guardReport.js +3 -5
- package/dist/lib/http/routes/panorama.js +12 -12
- package/dist/lib/http/routes/recipes.js +59 -8
- package/dist/lib/http/routes/remote.js +3 -13
- package/dist/lib/http/routes/search.js +11 -8
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
- package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
- package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
- package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
- package/dist/lib/injection/ServiceContainer.js +7 -4
- package/dist/lib/injection/ServiceMap.d.ts +20 -0
- package/dist/lib/injection/modules/AppModule.js +2 -1
- package/dist/lib/injection/modules/GuardModule.js +5 -5
- package/dist/lib/injection/modules/InfraModule.js +60 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
- package/dist/lib/injection/modules/PanoramaModule.js +16 -10
- package/dist/lib/injection/modules/VectorModule.js +3 -0
- package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
- package/dist/lib/repository/audit/AuditRepository.js +272 -0
- package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
- package/dist/lib/repository/base/RepositoryBase.js +32 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
- package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
- package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
- package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
- package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
- package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
- package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
- package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
- package/dist/lib/repository/memory/MemoryRepository.js +260 -0
- package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
- package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
- package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
- package/dist/lib/repository/session/SessionRepository.js +110 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
- package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
- package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
- package/dist/lib/service/cleanup/CleanupService.js +8 -4
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
- package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
- package/dist/lib/service/evolution/ContentPatcher.js +48 -19
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
- package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
- package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
- package/dist/lib/service/evolution/DecayDetector.js +63 -57
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
- package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
- package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
- package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
- package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
- package/dist/lib/service/evolution/StagingManager.js +37 -95
- package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
- package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
- package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
- package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
- package/dist/lib/service/guard/ReverseGuard.js +21 -31
- package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
- package/dist/lib/service/guard/ViolationsStore.js +75 -69
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
- package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
- package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
- package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
- package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
- package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
- package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
- package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
- package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
- package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
- package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
- package/dist/lib/service/panorama/LayerInferrer.js +1 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
- package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
- package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
- package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
- package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
- package/dist/lib/service/panorama/PanoramaService.js +41 -66
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
- package/dist/lib/service/panorama/RoleRefiner.js +52 -283
- package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
- package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
- package/dist/lib/service/quality/QualityScorer.js +157 -83
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +32 -37
- package/dist/lib/service/signal/HitRecorder.js +5 -5
- package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
- package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
- package/dist/lib/service/skills/SignalCollector.js +28 -55
- package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
- package/dist/lib/service/skills/SkillAdvisor.js +30 -79
- package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
- package/dist/lib/service/vector/SyncCoordinator.js +25 -3
- package/dist/lib/service/vector/VectorService.d.ts +2 -0
- package/dist/lib/service/vector/VectorService.js +3 -0
- package/dist/lib/service/wiki/WikiGenerator.js +1 -1
- package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
- package/dist/lib/shared/LanguageProfiles.js +939 -0
- package/dist/lib/shared/LanguageService.d.ts +6 -0
- package/dist/lib/shared/LanguageService.js +16 -0
- package/dist/lib/shared/constants.d.ts +19 -19
- package/dist/lib/shared/constants.js +10 -10
- package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
- package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
- package/dist/lib/types/project-snapshot-builder.js +0 -1
- package/dist/lib/types/project-snapshot.d.ts +0 -1
- package/dist/lib/types/project-snapshot.js +0 -1
- package/dist/lib/types/snapshot-views.d.ts +0 -2
- package/dist/lib/types/snapshot-views.js +0 -1
- package/package.json +2 -1
- package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
- package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
- package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
- package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
- package/dist/lib/repository/base/BaseRepository.js +0 -226
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MemoryStore — 持久化记忆 SQLite
|
|
2
|
+
* MemoryStore — 持久化记忆 SQLite 存储层(Drizzle 类型安全版)
|
|
3
3
|
*
|
|
4
4
|
* 从 PersistentMemory.js 提取的 CRUD + SQL 基础设施。
|
|
5
5
|
* 负责:
|
|
6
|
-
* - 表结构确保 (#ensureTable)
|
|
7
|
-
* - SQL 预编译 (#prepareStatements)
|
|
8
6
|
* - 基本 CRUD: add, update, delete, get
|
|
9
7
|
* - 批量查询: getAllActive, size, getStats
|
|
10
8
|
* - 访问计数: touchAccess
|
|
@@ -13,13 +11,18 @@
|
|
|
13
11
|
* - 统计: getStats, clearBootstrapMemories
|
|
14
12
|
*
|
|
15
13
|
* 设计原则:
|
|
16
|
-
* -
|
|
17
|
-
* - update()
|
|
14
|
+
* - 大部分操作通过 Drizzle 类型安全 API
|
|
15
|
+
* - update() 使用 Drizzle 类型安全 partial update
|
|
16
|
+
* - embedding 已迁移至 MemoryEmbeddingStore (JSON sidecar)
|
|
18
17
|
* - 数据序列化/反序列化统一在此层处理
|
|
19
18
|
*
|
|
20
19
|
* @module MemoryStore
|
|
21
20
|
*/
|
|
22
21
|
import { randomUUID } from 'node:crypto';
|
|
22
|
+
import { and, avg, count, desc, eq, isNull, lt, or, sql } from 'drizzle-orm';
|
|
23
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
24
|
+
import * as schema from '#infra/database/drizzle/schema.js';
|
|
25
|
+
import { semanticMemories } from '#infra/database/drizzle/schema.js';
|
|
23
26
|
import { jaccardSimilarity, tokenizeForSimilarity } from '#shared/similarity.js';
|
|
24
27
|
// ─── 常量 ──────────────────────────────────────────────
|
|
25
28
|
/** 最大记忆条数 (防止无限膨胀) */
|
|
@@ -29,20 +32,40 @@ const ARCHIVE_DAYS = 30;
|
|
|
29
32
|
const FORGET_DAYS = 90;
|
|
30
33
|
export class MemoryStore {
|
|
31
34
|
#db;
|
|
32
|
-
|
|
33
|
-
#stmts = null;
|
|
34
|
-
/** 动态 update SQL 缓存 */
|
|
35
|
-
#updateStmtCache = new Map();
|
|
35
|
+
#drizzle;
|
|
36
36
|
/** @param db better-sqlite3 实例 (raw) */
|
|
37
37
|
constructor(db) {
|
|
38
38
|
this.#db = db;
|
|
39
|
+
this.#drizzle = drizzle(db, { schema });
|
|
39
40
|
this.#ensureTable();
|
|
40
|
-
this.#prepareStatements();
|
|
41
41
|
}
|
|
42
42
|
/** 获取原始 db 引用 (for transaction) */
|
|
43
43
|
get db() {
|
|
44
44
|
return this.#db;
|
|
45
45
|
}
|
|
46
|
+
/** 确保表存在 (兼容 :memory: 测试 DB) */
|
|
47
|
+
#ensureTable() {
|
|
48
|
+
this.#db.exec(`
|
|
49
|
+
CREATE TABLE IF NOT EXISTS semantic_memories (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
type TEXT NOT NULL DEFAULT 'fact',
|
|
52
|
+
content TEXT NOT NULL DEFAULT '',
|
|
53
|
+
source TEXT NOT NULL DEFAULT 'bootstrap',
|
|
54
|
+
importance REAL NOT NULL DEFAULT 5.0,
|
|
55
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
56
|
+
last_accessed_at TEXT,
|
|
57
|
+
created_at TEXT NOT NULL,
|
|
58
|
+
updated_at TEXT NOT NULL,
|
|
59
|
+
expires_at TEXT,
|
|
60
|
+
related_entities TEXT DEFAULT '[]',
|
|
61
|
+
related_memories TEXT DEFAULT '[]',
|
|
62
|
+
source_dimension TEXT,
|
|
63
|
+
source_evidence TEXT,
|
|
64
|
+
bootstrap_session TEXT,
|
|
65
|
+
tags TEXT DEFAULT '[]'
|
|
66
|
+
)
|
|
67
|
+
`);
|
|
68
|
+
}
|
|
46
69
|
// ═══════════════════════════════════════════════════════════
|
|
47
70
|
// 基本 CRUD
|
|
48
71
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -58,85 +81,81 @@ export class MemoryStore {
|
|
|
58
81
|
const expiresAt = memory.ttlDays
|
|
59
82
|
? new Date(Date.now() + memory.ttlDays * 86400_000).toISOString()
|
|
60
83
|
: null;
|
|
61
|
-
this.#
|
|
84
|
+
this.#drizzle
|
|
85
|
+
.insert(semanticMemories)
|
|
86
|
+
.values({
|
|
62
87
|
id,
|
|
63
88
|
type: memory.type || 'fact',
|
|
64
89
|
content,
|
|
65
90
|
source: memory.source || 'bootstrap',
|
|
66
91
|
importance,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
accessCount: 0,
|
|
93
|
+
lastAccessedAt: now,
|
|
94
|
+
createdAt: now,
|
|
95
|
+
updatedAt: now,
|
|
96
|
+
expiresAt,
|
|
97
|
+
relatedEntities: JSON.stringify(memory.relatedEntities || []),
|
|
98
|
+
relatedMemories: JSON.stringify([]),
|
|
99
|
+
sourceDimension: memory.sourceDimension || null,
|
|
100
|
+
sourceEvidence: memory.sourceEvidence || null,
|
|
101
|
+
bootstrapSession: memory.bootstrapSession || null,
|
|
77
102
|
tags: JSON.stringify(memory.tags || []),
|
|
78
|
-
|
|
79
|
-
|
|
103
|
+
})
|
|
104
|
+
.run();
|
|
80
105
|
return { id, action: 'ADD' };
|
|
81
106
|
}
|
|
82
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* 更新已有记忆
|
|
109
|
+
*/
|
|
83
110
|
update(id, updates) {
|
|
84
|
-
const existing = this.#
|
|
111
|
+
const existing = this.#drizzle
|
|
112
|
+
.select({ id: semanticMemories.id })
|
|
113
|
+
.from(semanticMemories)
|
|
114
|
+
.where(eq(semanticMemories.id, id))
|
|
115
|
+
.get();
|
|
85
116
|
if (!existing) {
|
|
86
117
|
return false;
|
|
87
118
|
}
|
|
88
119
|
const now = new Date().toISOString();
|
|
89
|
-
const
|
|
90
|
-
const params = { id };
|
|
120
|
+
const setFields = {};
|
|
91
121
|
if (updates.content !== undefined) {
|
|
92
|
-
|
|
93
|
-
params.content = updates.content.substring(0, 500);
|
|
122
|
+
setFields.content = updates.content.substring(0, 500);
|
|
94
123
|
}
|
|
95
124
|
if (updates.importance !== undefined) {
|
|
96
|
-
|
|
97
|
-
params.importance = Math.max(1, Math.min(10, updates.importance));
|
|
125
|
+
setFields.importance = Math.max(1, Math.min(10, updates.importance));
|
|
98
126
|
}
|
|
99
127
|
if (updates.accessCount !== undefined) {
|
|
100
|
-
|
|
101
|
-
params.access_count = updates.accessCount;
|
|
128
|
+
setFields.accessCount = updates.accessCount;
|
|
102
129
|
}
|
|
103
130
|
if (updates.relatedEntities !== undefined) {
|
|
104
|
-
|
|
105
|
-
params.related_entities = JSON.stringify(updates.relatedEntities);
|
|
131
|
+
setFields.relatedEntities = JSON.stringify(updates.relatedEntities);
|
|
106
132
|
}
|
|
107
133
|
if (updates.relatedMemories !== undefined) {
|
|
108
|
-
|
|
109
|
-
params.related_memories = JSON.stringify(updates.relatedMemories);
|
|
134
|
+
setFields.relatedMemories = JSON.stringify(updates.relatedMemories);
|
|
110
135
|
}
|
|
111
136
|
if (updates.tags !== undefined) {
|
|
112
|
-
|
|
113
|
-
params.tags = JSON.stringify(updates.tags);
|
|
137
|
+
setFields.tags = JSON.stringify(updates.tags);
|
|
114
138
|
}
|
|
115
|
-
if (
|
|
139
|
+
if (Object.keys(setFields).length === 0) {
|
|
116
140
|
return false;
|
|
117
141
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// 使用缓存的 prepared statement,避免每次 update 都 prepare 新 SQL
|
|
121
|
-
const cacheKey = fields.join(',');
|
|
122
|
-
let stmt = this.#updateStmtCache.get(cacheKey);
|
|
123
|
-
if (!stmt) {
|
|
124
|
-
const sql = `UPDATE semantic_memories SET ${fields.join(', ')} WHERE id = @id`;
|
|
125
|
-
stmt = this.#db.prepare(sql);
|
|
126
|
-
this.#updateStmtCache.set(cacheKey, stmt);
|
|
127
|
-
}
|
|
128
|
-
stmt.run(params);
|
|
142
|
+
setFields.updatedAt = now;
|
|
143
|
+
this.#drizzle.update(semanticMemories).set(setFields).where(eq(semanticMemories.id, id)).run();
|
|
129
144
|
return true;
|
|
130
145
|
}
|
|
131
146
|
/** 删除一条记忆 */
|
|
132
147
|
delete(id) {
|
|
133
|
-
const result = this.#
|
|
134
|
-
return result.changes > 0;
|
|
148
|
+
const result = this.#drizzle.delete(semanticMemories).where(eq(semanticMemories.id, id)).run();
|
|
149
|
+
return (result.changes ?? 0) > 0;
|
|
135
150
|
}
|
|
136
151
|
/** 按 ID 获取 */
|
|
137
152
|
get(id) {
|
|
138
|
-
const row = this.#
|
|
139
|
-
|
|
153
|
+
const row = this.#drizzle
|
|
154
|
+
.select()
|
|
155
|
+
.from(semanticMemories)
|
|
156
|
+
.where(eq(semanticMemories.id, id))
|
|
157
|
+
.get();
|
|
158
|
+
return row ? MemoryStore.deserialize(MemoryStore.#toRow(row)) : null;
|
|
140
159
|
}
|
|
141
160
|
// ═══════════════════════════════════════════════════════════
|
|
142
161
|
// 批量查询
|
|
@@ -147,32 +166,50 @@ export class MemoryStore {
|
|
|
147
166
|
*/
|
|
148
167
|
getAllActive({ source, type } = {}) {
|
|
149
168
|
const now = new Date().toISOString();
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
now,
|
|
153
|
-
source,
|
|
154
|
-
type,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
169
|
+
const notExpired = or(isNull(semanticMemories.expiresAt), sql `${semanticMemories.expiresAt} > ${now}`);
|
|
170
|
+
const conditions = [notExpired];
|
|
157
171
|
if (source) {
|
|
158
|
-
|
|
172
|
+
conditions.push(eq(semanticMemories.source, source));
|
|
159
173
|
}
|
|
160
174
|
if (type) {
|
|
161
|
-
|
|
175
|
+
conditions.push(eq(semanticMemories.type, type));
|
|
162
176
|
}
|
|
163
|
-
|
|
177
|
+
const rows = this.#drizzle
|
|
178
|
+
.select()
|
|
179
|
+
.from(semanticMemories)
|
|
180
|
+
.where(and(...conditions))
|
|
181
|
+
.orderBy(desc(semanticMemories.updatedAt))
|
|
182
|
+
.all();
|
|
183
|
+
return rows.map(MemoryStore.#toRow);
|
|
164
184
|
}
|
|
165
185
|
/** 获取候选记忆 (用于相似度搜索) */
|
|
166
186
|
getCandidates(type) {
|
|
167
187
|
const now = new Date().toISOString();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
188
|
+
const notExpired = or(isNull(semanticMemories.expiresAt), sql `${semanticMemories.expiresAt} > ${now}`);
|
|
189
|
+
const conditions = [notExpired];
|
|
190
|
+
if (type) {
|
|
191
|
+
conditions.push(eq(semanticMemories.type, type));
|
|
192
|
+
}
|
|
193
|
+
const rows = this.#drizzle
|
|
194
|
+
.select()
|
|
195
|
+
.from(semanticMemories)
|
|
196
|
+
.where(and(...conditions))
|
|
197
|
+
.orderBy(desc(semanticMemories.updatedAt))
|
|
198
|
+
.limit(50)
|
|
199
|
+
.all();
|
|
200
|
+
return rows.map(MemoryStore.#toRow);
|
|
171
201
|
}
|
|
172
202
|
/** 更新访问计数 */
|
|
173
203
|
touchAccess(id) {
|
|
174
204
|
try {
|
|
175
|
-
this.#
|
|
205
|
+
this.#drizzle
|
|
206
|
+
.update(semanticMemories)
|
|
207
|
+
.set({
|
|
208
|
+
accessCount: sql `${semanticMemories.accessCount} + 1`,
|
|
209
|
+
lastAccessedAt: new Date().toISOString(),
|
|
210
|
+
})
|
|
211
|
+
.where(eq(semanticMemories.id, id))
|
|
212
|
+
.run();
|
|
176
213
|
}
|
|
177
214
|
catch {
|
|
178
215
|
/* non-critical */
|
|
@@ -180,12 +217,13 @@ export class MemoryStore {
|
|
|
180
217
|
}
|
|
181
218
|
/** 记忆总数 */
|
|
182
219
|
size({ source } = {}) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
220
|
+
const condition = source ? eq(semanticMemories.source, source) : undefined;
|
|
221
|
+
const [row] = this.#drizzle
|
|
222
|
+
.select({ cnt: count() })
|
|
223
|
+
.from(semanticMemories)
|
|
224
|
+
.where(condition)
|
|
225
|
+
.all();
|
|
226
|
+
return row?.cnt ?? 0;
|
|
189
227
|
}
|
|
190
228
|
// ═══════════════════════════════════════════════════════════
|
|
191
229
|
// 维护
|
|
@@ -198,54 +236,79 @@ export class MemoryStore {
|
|
|
198
236
|
const now = new Date().toISOString();
|
|
199
237
|
const nowMs = Date.now();
|
|
200
238
|
const stats = { expired: 0, forgotten: 0, archived: 0, remaining: 0 };
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.
|
|
205
|
-
|
|
239
|
+
this.#drizzle.transaction((tx) => {
|
|
240
|
+
// 清除已过期
|
|
241
|
+
const expiredResult = tx
|
|
242
|
+
.delete(semanticMemories)
|
|
243
|
+
.where(and(sql `${semanticMemories.expiresAt} IS NOT NULL`, lt(semanticMemories.expiresAt, now)))
|
|
244
|
+
.run();
|
|
245
|
+
stats.expired = expiredResult.changes ?? 0;
|
|
246
|
+
// 遗忘:长期未访问且不重要的
|
|
206
247
|
const forgetThreshold = new Date(nowMs - FORGET_DAYS * 86400_000).toISOString();
|
|
207
|
-
const forgottenResult =
|
|
208
|
-
.
|
|
209
|
-
.
|
|
210
|
-
|
|
248
|
+
const forgottenResult = tx
|
|
249
|
+
.delete(semanticMemories)
|
|
250
|
+
.where(and(lt(semanticMemories.lastAccessedAt, forgetThreshold), lt(semanticMemories.importance, 7)))
|
|
251
|
+
.run();
|
|
252
|
+
stats.forgotten = forgottenResult.changes ?? 0;
|
|
253
|
+
// 归档:降低重要性
|
|
211
254
|
const archiveThreshold = new Date(nowMs - ARCHIVE_DAYS * 86400_000).toISOString();
|
|
212
|
-
const archiveResult =
|
|
213
|
-
.
|
|
214
|
-
.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
255
|
+
const archiveResult = tx
|
|
256
|
+
.update(semanticMemories)
|
|
257
|
+
.set({
|
|
258
|
+
importance: sql `MAX(1, ${semanticMemories.importance} - 1)`,
|
|
259
|
+
})
|
|
260
|
+
.where(and(lt(semanticMemories.lastAccessedAt, archiveThreshold), lt(semanticMemories.importance, 3)))
|
|
261
|
+
.run();
|
|
262
|
+
stats.archived = archiveResult.changes ?? 0;
|
|
263
|
+
const [remainRow] = tx.select({ cnt: count() }).from(semanticMemories).all();
|
|
264
|
+
stats.remaining = remainRow?.cnt ?? 0;
|
|
218
265
|
});
|
|
219
|
-
runCompact();
|
|
220
266
|
return stats;
|
|
221
267
|
}
|
|
222
268
|
/** 容量控制 */
|
|
223
269
|
enforceCapacity() {
|
|
224
|
-
const
|
|
225
|
-
|
|
270
|
+
const [row] = this.#drizzle.select({ cnt: count() }).from(semanticMemories).all();
|
|
271
|
+
const total = row?.cnt ?? 0;
|
|
272
|
+
if (total <= MAX_MEMORIES) {
|
|
226
273
|
return;
|
|
227
274
|
}
|
|
228
|
-
const excess =
|
|
229
|
-
this.#
|
|
230
|
-
.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
.run(excess);
|
|
275
|
+
const excess = total - MAX_MEMORIES;
|
|
276
|
+
this.#drizzle
|
|
277
|
+
.delete(semanticMemories)
|
|
278
|
+
.where(sql `${semanticMemories.id} IN (
|
|
279
|
+
SELECT ${semanticMemories.id} FROM ${semanticMemories}
|
|
280
|
+
ORDER BY ${semanticMemories.importance} ASC, ${semanticMemories.accessCount} ASC, ${semanticMemories.updatedAt} ASC
|
|
281
|
+
LIMIT ${excess}
|
|
282
|
+
)`)
|
|
283
|
+
.run();
|
|
238
284
|
}
|
|
239
285
|
/** 获取统计信息 */
|
|
240
286
|
getStats() {
|
|
241
|
-
const
|
|
242
|
-
const
|
|
243
|
-
|
|
287
|
+
const [totalRow] = this.#drizzle.select({ cnt: count() }).from(semanticMemories).all();
|
|
288
|
+
const total = totalRow?.cnt ?? 0;
|
|
289
|
+
const byType = this.#drizzle
|
|
290
|
+
.select({
|
|
291
|
+
type: semanticMemories.type,
|
|
292
|
+
cnt: count(),
|
|
293
|
+
})
|
|
294
|
+
.from(semanticMemories)
|
|
295
|
+
.groupBy(semanticMemories.type)
|
|
244
296
|
.all();
|
|
245
|
-
const bySource = this.#
|
|
246
|
-
.
|
|
297
|
+
const bySource = this.#drizzle
|
|
298
|
+
.select({
|
|
299
|
+
source: semanticMemories.source,
|
|
300
|
+
cnt: count(),
|
|
301
|
+
})
|
|
302
|
+
.from(semanticMemories)
|
|
303
|
+
.groupBy(semanticMemories.source)
|
|
304
|
+
.all();
|
|
305
|
+
const [avgRow] = this.#drizzle
|
|
306
|
+
.select({
|
|
307
|
+
avg: avg(semanticMemories.importance),
|
|
308
|
+
})
|
|
309
|
+
.from(semanticMemories)
|
|
247
310
|
.all();
|
|
248
|
-
const avgImportance =
|
|
311
|
+
const avgImportance = avgRow?.avg ? Number(avgRow.avg) : 0;
|
|
249
312
|
return {
|
|
250
313
|
total,
|
|
251
314
|
byType: Object.fromEntries(byType.map((r) => [r.type, r.cnt])),
|
|
@@ -255,10 +318,11 @@ export class MemoryStore {
|
|
|
255
318
|
}
|
|
256
319
|
/** 清除所有 bootstrap 来源的记忆 */
|
|
257
320
|
clearBootstrapMemories() {
|
|
258
|
-
const result = this.#
|
|
259
|
-
.
|
|
321
|
+
const result = this.#drizzle
|
|
322
|
+
.delete(semanticMemories)
|
|
323
|
+
.where(eq(semanticMemories.source, 'bootstrap'))
|
|
260
324
|
.run();
|
|
261
|
-
return result.changes;
|
|
325
|
+
return result.changes ?? 0;
|
|
262
326
|
}
|
|
263
327
|
// ═══════════════════════════════════════════════════════════
|
|
264
328
|
// 相似度搜索
|
|
@@ -326,7 +390,6 @@ export class MemoryStore {
|
|
|
326
390
|
sourceEvidence: row.source_evidence,
|
|
327
391
|
bootstrapSession: row.bootstrap_session,
|
|
328
392
|
tags: MemoryStore.safeParseJSON(row.tags, []),
|
|
329
|
-
embedding: row.embedding ? MemoryStore.deserializeEmbedding(row.embedding) : null,
|
|
330
393
|
};
|
|
331
394
|
}
|
|
332
395
|
static safeParseJSON(str, fallback) {
|
|
@@ -338,155 +401,27 @@ export class MemoryStore {
|
|
|
338
401
|
}
|
|
339
402
|
}
|
|
340
403
|
// ═══════════════════════════════════════════════════════════
|
|
341
|
-
//
|
|
404
|
+
// Private: Drizzle → MemoryRow 映射
|
|
342
405
|
// ═══════════════════════════════════════════════════════════
|
|
343
|
-
/**
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
.
|
|
352
|
-
.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const runBatch = this.#db.transaction(() => {
|
|
363
|
-
for (const entry of entries) {
|
|
364
|
-
const blob = MemoryStore.serializeEmbedding(entry.embedding);
|
|
365
|
-
const result = stmt.run(blob, entry.id);
|
|
366
|
-
updated += result.changes;
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
runBatch();
|
|
370
|
-
return updated;
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* 获取缺少向量嵌入的记忆 ID 和内容
|
|
374
|
-
* @param limit 最大返回数
|
|
375
|
-
*/
|
|
376
|
-
getWithoutEmbedding(limit = 50) {
|
|
377
|
-
return this.#db
|
|
378
|
-
.prepare('SELECT id, content FROM semantic_memories WHERE embedding IS NULL ORDER BY updated_at DESC LIMIT ?')
|
|
379
|
-
.all(limit);
|
|
380
|
-
}
|
|
381
|
-
/** 将 number[] 序列化为 Buffer (Float32Array → BLOB) */
|
|
382
|
-
static serializeEmbedding(embedding) {
|
|
383
|
-
const float32 = new Float32Array(embedding);
|
|
384
|
-
return Buffer.from(float32.buffer, float32.byteOffset, float32.byteLength);
|
|
385
|
-
}
|
|
386
|
-
/** 将 Buffer (BLOB) 反序列化为 number[] */
|
|
387
|
-
static deserializeEmbedding(blob) {
|
|
388
|
-
const float32 = new Float32Array(blob.buffer, blob.byteOffset, blob.byteLength / Float32Array.BYTES_PER_ELEMENT);
|
|
389
|
-
return Array.from(float32);
|
|
390
|
-
}
|
|
391
|
-
// ═══════════════════════════════════════════════════════════
|
|
392
|
-
// Private: DB 基础设施
|
|
393
|
-
// ═══════════════════════════════════════════════════════════
|
|
394
|
-
#ensureTable() {
|
|
395
|
-
const exists = this.#db
|
|
396
|
-
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='semantic_memories'")
|
|
397
|
-
.get();
|
|
398
|
-
if (!exists) {
|
|
399
|
-
this.#db.exec(`
|
|
400
|
-
CREATE TABLE IF NOT EXISTS semantic_memories (
|
|
401
|
-
id TEXT PRIMARY KEY,
|
|
402
|
-
type TEXT NOT NULL DEFAULT 'fact',
|
|
403
|
-
content TEXT NOT NULL DEFAULT '',
|
|
404
|
-
source TEXT NOT NULL DEFAULT 'bootstrap',
|
|
405
|
-
importance REAL NOT NULL DEFAULT 5.0,
|
|
406
|
-
access_count INTEGER NOT NULL DEFAULT 0,
|
|
407
|
-
last_accessed_at TEXT,
|
|
408
|
-
created_at TEXT NOT NULL,
|
|
409
|
-
updated_at TEXT NOT NULL,
|
|
410
|
-
expires_at TEXT,
|
|
411
|
-
related_entities TEXT DEFAULT '[]',
|
|
412
|
-
related_memories TEXT DEFAULT '[]',
|
|
413
|
-
source_dimension TEXT,
|
|
414
|
-
source_evidence TEXT,
|
|
415
|
-
bootstrap_session TEXT,
|
|
416
|
-
tags TEXT DEFAULT '[]',
|
|
417
|
-
embedding BLOB
|
|
418
|
-
)
|
|
419
|
-
`);
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
// 迁移: 为已有表添加 embedding 列
|
|
423
|
-
try {
|
|
424
|
-
this.#db.prepare('SELECT embedding FROM semantic_memories LIMIT 1').get();
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
this.#db.exec('ALTER TABLE semantic_memories ADD COLUMN embedding BLOB');
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
#prepareStatements() {
|
|
432
|
-
this.#stmts = {
|
|
433
|
-
insert: this.#db.prepare(`
|
|
434
|
-
INSERT INTO semantic_memories
|
|
435
|
-
(id, type, content, source, importance, access_count,
|
|
436
|
-
last_accessed_at, created_at, updated_at, expires_at,
|
|
437
|
-
related_entities, related_memories,
|
|
438
|
-
source_dimension, source_evidence, bootstrap_session, tags, embedding)
|
|
439
|
-
VALUES
|
|
440
|
-
(@id, @type, @content, @source, @importance, @access_count,
|
|
441
|
-
@last_accessed_at, @created_at, @updated_at, @expires_at,
|
|
442
|
-
@related_entities, @related_memories,
|
|
443
|
-
@source_dimension, @source_evidence, @bootstrap_session, @tags, @embedding)
|
|
444
|
-
`),
|
|
445
|
-
getById: this.#db.prepare('SELECT * FROM semantic_memories WHERE id = ?'),
|
|
446
|
-
deleteById: this.#db.prepare('DELETE FROM semantic_memories WHERE id = ?'),
|
|
447
|
-
touchAccess: this.#db.prepare(`
|
|
448
|
-
UPDATE semantic_memories
|
|
449
|
-
SET access_count = access_count + 1,
|
|
450
|
-
last_accessed_at = @now
|
|
451
|
-
WHERE id = @id
|
|
452
|
-
`),
|
|
453
|
-
getAllActive: this.#db.prepare(`
|
|
454
|
-
SELECT * FROM semantic_memories
|
|
455
|
-
WHERE (expires_at IS NULL OR expires_at > @now)
|
|
456
|
-
ORDER BY updated_at DESC
|
|
457
|
-
`),
|
|
458
|
-
getAllActiveBySource: this.#db.prepare(`
|
|
459
|
-
SELECT * FROM semantic_memories
|
|
460
|
-
WHERE (expires_at IS NULL OR expires_at > @now)
|
|
461
|
-
AND source = @source
|
|
462
|
-
ORDER BY updated_at DESC
|
|
463
|
-
`),
|
|
464
|
-
getAllActiveByType: this.#db.prepare(`
|
|
465
|
-
SELECT * FROM semantic_memories
|
|
466
|
-
WHERE (expires_at IS NULL OR expires_at > @now)
|
|
467
|
-
AND type = @type
|
|
468
|
-
ORDER BY updated_at DESC
|
|
469
|
-
`),
|
|
470
|
-
getAllActiveBySourceAndType: this.#db.prepare(`
|
|
471
|
-
SELECT * FROM semantic_memories
|
|
472
|
-
WHERE (expires_at IS NULL OR expires_at > @now)
|
|
473
|
-
AND source = @source
|
|
474
|
-
AND type = @type
|
|
475
|
-
ORDER BY updated_at DESC
|
|
476
|
-
`),
|
|
477
|
-
getByContent: this.#db.prepare(`
|
|
478
|
-
SELECT * FROM semantic_memories
|
|
479
|
-
WHERE type = @type
|
|
480
|
-
AND (expires_at IS NULL OR expires_at > @now)
|
|
481
|
-
ORDER BY updated_at DESC
|
|
482
|
-
LIMIT 50
|
|
483
|
-
`),
|
|
484
|
-
getAll: this.#db.prepare(`
|
|
485
|
-
SELECT * FROM semantic_memories
|
|
486
|
-
WHERE (expires_at IS NULL OR expires_at > @now)
|
|
487
|
-
ORDER BY updated_at DESC
|
|
488
|
-
LIMIT 50
|
|
489
|
-
`),
|
|
406
|
+
/** Drizzle camelCase row → MemoryRow snake_case (保持向后兼容) */
|
|
407
|
+
static #toRow(row) {
|
|
408
|
+
return {
|
|
409
|
+
id: row.id,
|
|
410
|
+
type: row.type,
|
|
411
|
+
content: row.content,
|
|
412
|
+
source: row.source,
|
|
413
|
+
importance: row.importance,
|
|
414
|
+
access_count: row.accessCount,
|
|
415
|
+
last_accessed_at: row.lastAccessedAt,
|
|
416
|
+
created_at: row.createdAt,
|
|
417
|
+
updated_at: row.updatedAt,
|
|
418
|
+
expires_at: row.expiresAt,
|
|
419
|
+
related_entities: row.relatedEntities ?? '[]',
|
|
420
|
+
related_memories: row.relatedMemories ?? '[]',
|
|
421
|
+
source_dimension: row.sourceDimension,
|
|
422
|
+
source_evidence: row.sourceEvidence,
|
|
423
|
+
bootstrap_session: row.bootstrapSession,
|
|
424
|
+
tags: row.tags ?? '[]',
|
|
490
425
|
};
|
|
491
426
|
}
|
|
492
427
|
}
|
|
@@ -21,12 +21,14 @@
|
|
|
21
21
|
* @module PersistentMemory
|
|
22
22
|
*/
|
|
23
23
|
import type { CandidateMemory, ConsolidateOptions, ConsolidateStats } from './MemoryConsolidator.js';
|
|
24
|
+
import type { MemoryEmbeddingStore } from './MemoryEmbeddingStore.js';
|
|
24
25
|
import type { AppendEntry, EmbeddingFn, LoadOptions, PromptSectionOptions, RetrieveOptions, ScoredMemory } from './MemoryRetriever.js';
|
|
25
26
|
import type { DeserializedMemory, MemoryInput, MemoryUpdates, SqliteDatabase } from './MemoryStore.js';
|
|
26
27
|
/** PersistentMemory 构造选项 */
|
|
27
28
|
export interface PersistentMemoryOptions {
|
|
28
29
|
logger?: MemoryLogger | null;
|
|
29
30
|
embeddingFn?: EmbeddingFn;
|
|
31
|
+
embeddingStore?: MemoryEmbeddingStore;
|
|
30
32
|
}
|
|
31
33
|
/** Logger 接口 */
|
|
32
34
|
interface MemoryLogger {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @module PersistentMemory
|
|
22
22
|
*/
|
|
23
|
+
import { unwrapRawDb } from '../../repository/search/SearchRepoAdapter.js';
|
|
23
24
|
import { MemoryConsolidator } from './MemoryConsolidator.js';
|
|
24
25
|
import { MemoryRetriever } from './MemoryRetriever.js';
|
|
25
26
|
import { MemoryStore } from './MemoryStore.js';
|
|
@@ -30,17 +31,15 @@ export class PersistentMemory {
|
|
|
30
31
|
#logger;
|
|
31
32
|
/** @param db better-sqlite3 实例 */
|
|
32
33
|
constructor(db, opts = {}) {
|
|
33
|
-
const { logger, embeddingFn } = typeof opts === 'object' && opts !== null ? opts : {};
|
|
34
|
+
const { logger, embeddingFn, embeddingStore } = typeof opts === 'object' && opts !== null ? opts : {};
|
|
34
35
|
if (!db) {
|
|
35
36
|
throw new Error('PersistentMemory requires a database instance');
|
|
36
37
|
}
|
|
37
|
-
const rawDb =
|
|
38
|
-
? db.getDb()
|
|
39
|
-
: db;
|
|
38
|
+
const rawDb = unwrapRawDb(db);
|
|
40
39
|
this.#logger = logger || null;
|
|
41
40
|
// 组装子模块
|
|
42
41
|
this.#store = new MemoryStore(rawDb);
|
|
43
|
-
this.#retriever = new MemoryRetriever(this.#store, { embeddingFn });
|
|
42
|
+
this.#retriever = new MemoryRetriever(this.#store, { embeddingFn, embeddingStore });
|
|
44
43
|
this.#consolidator = new MemoryConsolidator(this.#store, { logger: this.#logger });
|
|
45
44
|
}
|
|
46
45
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SessionStore — Bootstrap 会话级存储 (合并 EpisodicMemory + ToolResultCache)
|
|
3
3
|
*
|
|
4
|
-
* 设计来源: docs/copilot/memory-system-redesign.md §4.4, §6.3
|
|
5
|
-
*
|
|
6
4
|
* 内部子系统:
|
|
7
5
|
* 1. DimensionReports — 跨维度分析报告 + 结构化证据 + 交叉引用 (from EpisodicMemory)
|
|
8
6
|
* 2. ReadOnlyCache — 只读工具结果缓存 (from ToolResultCache, 排除副作用工具 B3 fix)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SessionStore — Bootstrap 会话级存储 (合并 EpisodicMemory + ToolResultCache)
|
|
3
3
|
*
|
|
4
|
-
* 设计来源: docs/copilot/memory-system-redesign.md §4.4, §6.3
|
|
5
|
-
*
|
|
6
4
|
* 内部子系统:
|
|
7
5
|
* 1. DimensionReports — 跨维度分析报告 + 结构化证据 + 交叉引用 (from EpisodicMemory)
|
|
8
6
|
* 2. ReadOnlyCache — 只读工具结果缓存 (from ToolResultCache, 排除副作用工具 B3 fix)
|