noormme 1.0.6 → 1.2.0
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 +92 -63
- package/dist/cjs/agentic/ActionJournal.js +13 -9
- package/dist/cjs/agentic/CapabilityManager.d.ts +9 -4
- package/dist/cjs/agentic/CapabilityManager.js +113 -17
- package/dist/cjs/agentic/CognitiveRepository.js +19 -9
- package/dist/cjs/agentic/ContextBuffer.js +24 -12
- package/dist/cjs/agentic/Cortex.d.ts +8 -1
- package/dist/cjs/agentic/Cortex.js +30 -7
- package/dist/cjs/agentic/EpisodicMemory.js +7 -5
- package/dist/cjs/agentic/PersonaManager.js +16 -8
- package/dist/cjs/agentic/PolicyEnforcer.js +31 -12
- package/dist/cjs/agentic/ResourceMonitor.js +4 -4
- package/dist/cjs/agentic/SessionCompressor.js +22 -14
- package/dist/cjs/agentic/SessionManager.js +36 -18
- package/dist/cjs/agentic/VectorIndexer.js +22 -18
- package/dist/cjs/agentic/improvement/AblationEngine.js +22 -15
- package/dist/cjs/agentic/improvement/ActionRefiner.js +12 -10
- package/dist/cjs/agentic/improvement/ConflictResolver.js +5 -5
- package/dist/cjs/agentic/improvement/CortexJanitor.d.ts +1 -1
- package/dist/cjs/agentic/improvement/CortexJanitor.js +64 -27
- package/dist/cjs/agentic/improvement/CuriosityEngine.d.ts +2 -2
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +68 -59
- package/dist/cjs/agentic/improvement/EvolutionRitual.d.ts +24 -0
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +91 -0
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.d.ts +5 -0
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +80 -7
- package/dist/cjs/agentic/improvement/GoalArchitect.d.ts +2 -2
- package/dist/cjs/agentic/improvement/GoalArchitect.js +20 -18
- package/dist/cjs/agentic/improvement/GovernanceManager.d.ts +1 -1
- package/dist/cjs/agentic/improvement/GovernanceManager.js +85 -49
- package/dist/cjs/agentic/improvement/HiveLink.d.ts +9 -0
- package/dist/cjs/agentic/improvement/HiveLink.js +120 -26
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.d.ts +2 -0
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +101 -47
- package/dist/cjs/agentic/improvement/RecursiveReasoner.d.ts +7 -1
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +106 -22
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +34 -22
- package/dist/cjs/agentic/improvement/RuleEngine.js +22 -17
- package/dist/cjs/agentic/improvement/SelfEvolution.js +24 -18
- package/dist/cjs/agentic/improvement/SelfTestRegistry.js +18 -15
- package/dist/cjs/agentic/improvement/SkillSynthesizer.d.ts +48 -0
- package/dist/cjs/agentic/improvement/SkillSynthesizer.js +288 -0
- package/dist/cjs/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/cjs/agentic/improvement/StrategicPlanner.d.ts +1 -1
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +129 -55
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.js +26 -12
- package/dist/cjs/agentic/telemetry/EventHarvester.js +3 -2
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.js +13 -4
- package/dist/cjs/cache/cache-manager.js +7 -4
- package/dist/cjs/cli/commands/analyze.js +5 -4
- package/dist/cjs/cli/commands/generate.js +81 -44
- package/dist/cjs/cli/commands/init.js +7 -3
- package/dist/cjs/cli/commands/inspect.js +139 -36
- package/dist/cjs/cli/commands/migrate.js +5 -4
- package/dist/cjs/cli/commands/optimize.js +4 -4
- package/dist/cjs/cli/commands/status.js +9 -7
- package/dist/cjs/cli/commands/watch.js +7 -6
- package/dist/cjs/cli/index.js +2 -2
- package/dist/cjs/cli/ui/spinner.d.ts +15 -0
- package/dist/cjs/cli/ui/spinner.js +76 -0
- package/dist/cjs/dialect/database-introspector.js +3 -1
- package/dist/cjs/dialect/postgresql/postgresql-driver.js +3 -1
- package/dist/cjs/dialect/postgresql/postgresql-features.js +18 -8
- package/dist/cjs/dialect/postgresql/postgresql-introspector.js +2 -2
- package/dist/cjs/dialect/sqlite/sqlite-auto-indexer.js +47 -33
- package/dist/cjs/dialect/sqlite/sqlite-auto-optimizer.js +8 -7
- package/dist/cjs/dialect/sqlite/sqlite-driver.js +2 -2
- package/dist/cjs/dialect/sqlite/sqlite-introspector.js +15 -12
- package/dist/cjs/edge-runtime/edge-config.js +21 -19
- package/dist/cjs/errors/NoormError.js +22 -20
- package/dist/cjs/helpers/agent-schema.js +3 -0
- package/dist/cjs/helpers/postgresql.js +7 -4
- package/dist/cjs/helpers/schema-evolution.js +31 -6
- package/dist/cjs/index.d.ts +18 -16
- package/dist/cjs/logging/logger.js +8 -4
- package/dist/cjs/migration/data_migrator.js +12 -11
- package/dist/cjs/migration/database_migration_manager.js +17 -13
- package/dist/cjs/migration/schema_differ.js +22 -14
- package/dist/cjs/migration/schema_introspector.js +8 -8
- package/dist/cjs/migration/type_mapper.js +68 -67
- package/dist/cjs/noormme.js +54 -37
- package/dist/cjs/performance/index.js +5 -5
- package/dist/cjs/performance/query-optimizer.js +26 -21
- package/dist/cjs/performance/services/cache-service.js +26 -16
- package/dist/cjs/performance/services/connection-factory.js +28 -23
- package/dist/cjs/performance/services/metrics-collector.js +41 -36
- package/dist/cjs/performance/utils/query-parser.js +15 -16
- package/dist/cjs/relationships/relationship-engine.js +10 -8
- package/dist/cjs/repository/repository-factory.js +97 -38
- package/dist/cjs/schema/core/coordinators/schema-discovery.coordinator.js +1 -3
- package/dist/cjs/schema/core/discovery/relationship-discovery.js +16 -16
- package/dist/cjs/schema/core/discovery/table-metadata-discovery.js +9 -9
- package/dist/cjs/schema/core/discovery/view-discovery.js +5 -4
- package/dist/cjs/schema/core/factories/discovery-factory.js +4 -4
- package/dist/cjs/schema/core/utils/name-generator.js +14 -5
- package/dist/cjs/schema/core/utils/type-mapper.js +24 -24
- package/dist/cjs/schema/dialects/postgresql/postgresql-discovery.coordinator.js +8 -7
- package/dist/cjs/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +17 -15
- package/dist/cjs/schema/dialects/sqlite/discovery/sqlite-index-discovery.js +8 -8
- package/dist/cjs/schema/dialects/sqlite/introspection/sqlite-schema-introspector.js +6 -11
- package/dist/cjs/schema/dialects/sqlite/sqlite-discovery.coordinator.js +14 -13
- package/dist/cjs/schema/test/basic-schema-test.js +11 -9
- package/dist/cjs/schema/test/dialect-capabilities.test.js +6 -6
- package/dist/cjs/schema/test/discovery-factory.test.js +2 -2
- package/dist/cjs/schema/test/error-handling.test.js +8 -6
- package/dist/cjs/schema/test/integration.test.js +24 -18
- package/dist/cjs/schema/test/schema-discovery-coordinator.test.js +9 -9
- package/dist/cjs/schema/test/simple-schema-test.js +9 -9
- package/dist/cjs/schema/test/sqlite-discovery-coordinator.test.js +64 -48
- package/dist/cjs/schema/test/test-runner.js +3 -3
- package/dist/cjs/sqlite-migration/index.d.ts +2 -2
- package/dist/cjs/sqlite-migration/sqlite-migration-manager.js +21 -17
- package/dist/cjs/sqlite-migration/sqlite-migration-provider.js +38 -34
- package/dist/cjs/testing/test-utils.js +36 -34
- package/dist/cjs/types/index.d.ts +61 -4
- package/dist/cjs/types/index.js +6 -3
- package/dist/cjs/types/type-generator.js +46 -42
- package/dist/cjs/util/safe-sql-helpers.js +1 -1
- package/dist/cjs/util/security-validator.js +20 -9
- package/dist/cjs/utils/errorHelpers.js +20 -10
- package/dist/cjs/watch/schema-watcher.js +22 -23
- package/dist/esm/agentic/ActionJournal.js +13 -9
- package/dist/esm/agentic/CapabilityManager.d.ts +9 -4
- package/dist/esm/agentic/CapabilityManager.js +113 -17
- package/dist/esm/agentic/CognitiveRepository.js +19 -9
- package/dist/esm/agentic/ContextBuffer.js +24 -12
- package/dist/esm/agentic/Cortex.d.ts +8 -1
- package/dist/esm/agentic/Cortex.js +30 -7
- package/dist/esm/agentic/EpisodicMemory.js +7 -5
- package/dist/esm/agentic/PersonaManager.js +16 -8
- package/dist/esm/agentic/PolicyEnforcer.js +31 -12
- package/dist/esm/agentic/ResourceMonitor.js +4 -4
- package/dist/esm/agentic/SessionCompressor.js +22 -14
- package/dist/esm/agentic/SessionManager.js +36 -18
- package/dist/esm/agentic/VectorIndexer.js +22 -18
- package/dist/esm/agentic/improvement/AblationEngine.js +22 -15
- package/dist/esm/agentic/improvement/ActionRefiner.js +12 -10
- package/dist/esm/agentic/improvement/ConflictResolver.js +5 -5
- package/dist/esm/agentic/improvement/CortexJanitor.d.ts +1 -1
- package/dist/esm/agentic/improvement/CortexJanitor.js +64 -27
- package/dist/esm/agentic/improvement/CuriosityEngine.d.ts +2 -2
- package/dist/esm/agentic/improvement/CuriosityEngine.js +68 -59
- package/dist/esm/agentic/improvement/EvolutionRitual.d.ts +24 -0
- package/dist/esm/agentic/improvement/EvolutionRitual.js +88 -0
- package/dist/esm/agentic/improvement/EvolutionaryPilot.d.ts +5 -0
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +80 -7
- package/dist/esm/agentic/improvement/GoalArchitect.d.ts +2 -2
- package/dist/esm/agentic/improvement/GoalArchitect.js +20 -18
- package/dist/esm/agentic/improvement/GovernanceManager.d.ts +1 -1
- package/dist/esm/agentic/improvement/GovernanceManager.js +85 -49
- package/dist/esm/agentic/improvement/HiveLink.d.ts +9 -0
- package/dist/esm/agentic/improvement/HiveLink.js +120 -26
- package/dist/esm/agentic/improvement/KnowledgeDistiller.d.ts +2 -0
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +101 -47
- package/dist/esm/agentic/improvement/RecursiveReasoner.d.ts +7 -1
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +106 -22
- package/dist/esm/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +34 -22
- package/dist/esm/agentic/improvement/RuleEngine.js +22 -17
- package/dist/esm/agentic/improvement/SelfEvolution.js +24 -18
- package/dist/esm/agentic/improvement/SelfTestRegistry.js +18 -15
- package/dist/esm/agentic/improvement/SkillSynthesizer.d.ts +48 -0
- package/dist/esm/agentic/improvement/SkillSynthesizer.js +285 -0
- package/dist/esm/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/esm/agentic/improvement/StrategicPlanner.d.ts +1 -1
- package/dist/esm/agentic/improvement/StrategicPlanner.js +129 -55
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.js +26 -12
- package/dist/esm/agentic/telemetry/EventHarvester.js +3 -2
- package/dist/esm/agentic/telemetry/ResearchAlchemist.js +13 -4
- package/dist/esm/cache/cache-manager.js +7 -4
- package/dist/esm/cli/commands/analyze.js +5 -4
- package/dist/esm/cli/commands/generate.js +82 -45
- package/dist/esm/cli/commands/init.js +8 -4
- package/dist/esm/cli/commands/inspect.js +140 -37
- package/dist/esm/cli/commands/migrate.js +5 -4
- package/dist/esm/cli/commands/optimize.js +4 -4
- package/dist/esm/cli/commands/status.js +9 -7
- package/dist/esm/cli/commands/watch.js +7 -6
- package/dist/esm/cli/index.js +2 -2
- package/dist/esm/cli/ui/spinner.d.ts +15 -0
- package/dist/esm/cli/ui/spinner.js +70 -0
- package/dist/esm/dialect/database-introspector.js +3 -1
- package/dist/esm/dialect/postgresql/postgresql-driver.js +3 -1
- package/dist/esm/dialect/postgresql/postgresql-features.js +18 -8
- package/dist/esm/dialect/postgresql/postgresql-introspector.js +2 -2
- package/dist/esm/dialect/sqlite/sqlite-auto-indexer.js +47 -33
- package/dist/esm/dialect/sqlite/sqlite-auto-optimizer.js +8 -7
- package/dist/esm/dialect/sqlite/sqlite-driver.js +2 -2
- package/dist/esm/dialect/sqlite/sqlite-introspector.js +15 -12
- package/dist/esm/dynamic/dynamic.js +1 -1
- package/dist/esm/edge-runtime/edge-config.js +21 -19
- package/dist/esm/errors/NoormError.js +22 -20
- package/dist/esm/helpers/agent-schema.js +3 -0
- package/dist/esm/helpers/postgresql.js +7 -4
- package/dist/esm/helpers/schema-evolution.js +31 -6
- package/dist/esm/index.d.ts +18 -16
- package/dist/esm/index.js +2 -2
- package/dist/esm/logging/logger.js +8 -4
- package/dist/esm/migration/data_migrator.js +12 -11
- package/dist/esm/migration/database_migration_manager.js +18 -14
- package/dist/esm/migration/schema_differ.js +22 -14
- package/dist/esm/migration/schema_introspector.js +8 -8
- package/dist/esm/migration/type_mapper.js +68 -67
- package/dist/esm/noormme.js +54 -37
- package/dist/esm/performance/index.js +5 -5
- package/dist/esm/performance/query-optimizer.js +26 -21
- package/dist/esm/performance/services/cache-service.js +26 -16
- package/dist/esm/performance/services/connection-factory.js +28 -23
- package/dist/esm/performance/services/metrics-collector.js +41 -36
- package/dist/esm/performance/utils/query-parser.js +15 -16
- package/dist/esm/raw-builder/sql.js +1 -1
- package/dist/esm/relationships/relationship-engine.js +10 -8
- package/dist/esm/repository/repository-factory.js +98 -39
- package/dist/esm/schema/builders/alter-table-add-index-builder.js +1 -1
- package/dist/esm/schema/builders/create-index-builder.js +2 -2
- package/dist/esm/schema/core/coordinators/schema-discovery.coordinator.js +1 -3
- package/dist/esm/schema/core/discovery/relationship-discovery.js +16 -16
- package/dist/esm/schema/core/discovery/table-metadata-discovery.js +9 -9
- package/dist/esm/schema/core/discovery/view-discovery.js +5 -4
- package/dist/esm/schema/core/factories/discovery-factory.js +4 -4
- package/dist/esm/schema/core/utils/name-generator.js +14 -5
- package/dist/esm/schema/core/utils/type-mapper.js +24 -24
- package/dist/esm/schema/dialects/postgresql/postgresql-discovery.coordinator.js +8 -7
- package/dist/esm/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +17 -15
- package/dist/esm/schema/dialects/sqlite/discovery/sqlite-index-discovery.js +8 -8
- package/dist/esm/schema/dialects/sqlite/introspection/sqlite-schema-introspector.js +6 -11
- package/dist/esm/schema/dialects/sqlite/sqlite-discovery.coordinator.js +14 -13
- package/dist/esm/schema/test/basic-schema-test.js +11 -9
- package/dist/esm/schema/test/dialect-capabilities.test.js +6 -6
- package/dist/esm/schema/test/discovery-factory.test.js +2 -2
- package/dist/esm/schema/test/error-handling.test.js +8 -6
- package/dist/esm/schema/test/integration.test.js +24 -18
- package/dist/esm/schema/test/schema-discovery-coordinator.test.js +9 -9
- package/dist/esm/schema/test/simple-schema-test.js +9 -9
- package/dist/esm/schema/test/sqlite-discovery-coordinator.test.js +64 -48
- package/dist/esm/schema/test/test-runner.js +3 -3
- package/dist/esm/sqlite-migration/index.d.ts +2 -2
- package/dist/esm/sqlite-migration/sqlite-migration-manager.js +21 -17
- package/dist/esm/sqlite-migration/sqlite-migration-provider.js +38 -34
- package/dist/esm/testing/test-utils.js +36 -34
- package/dist/esm/types/index.d.ts +61 -4
- package/dist/esm/types/index.js +6 -3
- package/dist/esm/types/type-generator.js +46 -42
- package/dist/esm/util/safe-sql-helpers.js +1 -1
- package/dist/esm/util/security-validator.js +20 -9
- package/dist/esm/utils/errorHelpers.js +21 -11
- package/dist/esm/watch/schema-watcher.js +22 -23
- package/package.json +40 -44
|
@@ -11,6 +11,7 @@ class KnowledgeDistiller {
|
|
|
11
11
|
config;
|
|
12
12
|
knowledgeTable;
|
|
13
13
|
linksTable;
|
|
14
|
+
bloomFilter = new Set();
|
|
14
15
|
constructor(db, // accepting any Kysely but casting internally for our specific tables
|
|
15
16
|
config = {}) {
|
|
16
17
|
this.db = db;
|
|
@@ -28,6 +29,28 @@ class KnowledgeDistiller {
|
|
|
28
29
|
* Add or update a knowledge item with robust merging and transaction support.
|
|
29
30
|
*/
|
|
30
31
|
async distill(entity, fact, confidence, sourceSessionId, tags = [], metadata = {}, source = 'assistant') {
|
|
32
|
+
// Pass 6: Bloom filter Heuristic
|
|
33
|
+
// Lightweight de-duplication for ultra-scale throughput.
|
|
34
|
+
// If the fact matches a very recent pattern, skip expensive DB checks.
|
|
35
|
+
const factHash = this.bloomHash(`${entity}:${fact}`);
|
|
36
|
+
if (this.bloomFilter.has(factHash)) {
|
|
37
|
+
// Likely a duplicate, but we'll do a quick check if it's "verified" to avoid re-distilling
|
|
38
|
+
console.log(`[KnowledgeDistiller] Bloom filter hit for ${entity}. Skipping redundant distillation.`);
|
|
39
|
+
const quickMatch = await this.db
|
|
40
|
+
.selectFrom(this.knowledgeTable)
|
|
41
|
+
.select(['id', 'status'])
|
|
42
|
+
.where('entity', '=', entity)
|
|
43
|
+
.where('fact', '=', fact)
|
|
44
|
+
.executeTakeFirst();
|
|
45
|
+
if (quickMatch &&
|
|
46
|
+
quickMatch.status === 'verified' &&
|
|
47
|
+
source !== 'user') {
|
|
48
|
+
return (await this.getKnowledgeByEntity(entity)).find((k) => k.fact === fact);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.bloomFilter.add(factHash);
|
|
52
|
+
if (this.bloomFilter.size > 1000)
|
|
53
|
+
this.bloomFilter.clear(); // Simple rolling window
|
|
31
54
|
return await this.db.transaction().execute(async (trx) => {
|
|
32
55
|
// Check for exact match first
|
|
33
56
|
const existing = await trx
|
|
@@ -38,10 +61,14 @@ class KnowledgeDistiller {
|
|
|
38
61
|
.executeTakeFirst();
|
|
39
62
|
if (existing) {
|
|
40
63
|
// Merge tags
|
|
41
|
-
const existingTags = existing.tags
|
|
64
|
+
const existingTags = existing.tags
|
|
65
|
+
? JSON.parse(existing.tags)
|
|
66
|
+
: [];
|
|
42
67
|
const mergedTags = Array.from(new Set([...existingTags, ...tags]));
|
|
43
68
|
// Merge metadata
|
|
44
|
-
const existingMeta = existing.metadata
|
|
69
|
+
const existingMeta = existing.metadata
|
|
70
|
+
? JSON.parse(existing.metadata)
|
|
71
|
+
: {};
|
|
45
72
|
// Hallucination Prevention: Tracking contributing sessions
|
|
46
73
|
const sessions = new Set(existingMeta.sessions || []);
|
|
47
74
|
if (sourceSessionId)
|
|
@@ -50,7 +77,7 @@ class KnowledgeDistiller {
|
|
|
50
77
|
...existingMeta,
|
|
51
78
|
...metadata,
|
|
52
79
|
sessions: Array.from(sessions),
|
|
53
|
-
session_count: sessions.size
|
|
80
|
+
session_count: sessions.size,
|
|
54
81
|
};
|
|
55
82
|
// Source weighting: User verification boosts confidence faster
|
|
56
83
|
const boost = source === 'user' ? 0.2 : 0.05;
|
|
@@ -68,7 +95,7 @@ class KnowledgeDistiller {
|
|
|
68
95
|
tags: JSON.stringify(mergedTags),
|
|
69
96
|
metadata: JSON.stringify(mergedMeta),
|
|
70
97
|
updated_at: new Date(),
|
|
71
|
-
source_session_id: sourceSessionId ?? existing.source_session_id
|
|
98
|
+
source_session_id: sourceSessionId ?? existing.source_session_id,
|
|
72
99
|
})
|
|
73
100
|
.where('id', '=', existing.id)
|
|
74
101
|
.returningAll()
|
|
@@ -82,7 +109,7 @@ class KnowledgeDistiller {
|
|
|
82
109
|
...metadata,
|
|
83
110
|
source,
|
|
84
111
|
sessions: sourceSessionId ? [sourceSessionId] : [],
|
|
85
|
-
session_count: sourceSessionId ? 1 : 0
|
|
112
|
+
session_count: sourceSessionId ? 1 : 0,
|
|
86
113
|
};
|
|
87
114
|
const created = await trx
|
|
88
115
|
.insertInto(this.knowledgeTable)
|
|
@@ -95,7 +122,7 @@ class KnowledgeDistiller {
|
|
|
95
122
|
tags: JSON.stringify(tags),
|
|
96
123
|
metadata: JSON.stringify(initialMeta),
|
|
97
124
|
created_at: new Date(),
|
|
98
|
-
updated_at: new Date()
|
|
125
|
+
updated_at: new Date(),
|
|
99
126
|
})
|
|
100
127
|
.returningAll()
|
|
101
128
|
.executeTakeFirstOrThrow();
|
|
@@ -117,7 +144,9 @@ class KnowledgeDistiller {
|
|
|
117
144
|
.executeTakeFirst();
|
|
118
145
|
if (!existing)
|
|
119
146
|
return null;
|
|
120
|
-
const metadata = typeof existing.metadata === 'string'
|
|
147
|
+
const metadata = typeof existing.metadata === 'string'
|
|
148
|
+
? JSON.parse(existing.metadata)
|
|
149
|
+
: existing.metadata || {};
|
|
121
150
|
// Hallucination Guard: Cap confidence for non-user sources until cross-session verification
|
|
122
151
|
let maxConfidence = 1.0;
|
|
123
152
|
if (metadata.source !== 'user' && (metadata.session_count || 0) < 3) {
|
|
@@ -135,7 +164,7 @@ class KnowledgeDistiller {
|
|
|
135
164
|
.set({
|
|
136
165
|
confidence: newConfidence,
|
|
137
166
|
status: newStatus,
|
|
138
|
-
updated_at: new Date()
|
|
167
|
+
updated_at: new Date(),
|
|
139
168
|
})
|
|
140
169
|
.where('id', '=', id)
|
|
141
170
|
.returningAll()
|
|
@@ -153,14 +182,14 @@ class KnowledgeDistiller {
|
|
|
153
182
|
.where('entity', '=', entity)
|
|
154
183
|
.orderBy('confidence', 'desc');
|
|
155
184
|
const items = (await query.execute());
|
|
156
|
-
const parsed = items.map(i => this.parseKnowledge(i));
|
|
185
|
+
const parsed = items.map((i) => this.parseKnowledge(i));
|
|
157
186
|
let filtered = parsed;
|
|
158
187
|
if (filterTags && filterTags.length > 0) {
|
|
159
|
-
filtered = parsed.filter(item => item.tags?.some(tag => filterTags.includes(tag)));
|
|
188
|
+
filtered = parsed.filter((item) => item.tags?.some((tag) => filterTags.includes(tag)));
|
|
160
189
|
}
|
|
161
190
|
// Record hits asynchronously
|
|
162
191
|
for (const item of filtered) {
|
|
163
|
-
this.recordHit(item.id).catch(err => console.error(`[KnowledgeDistiller] Failed to record hit for ${item.id}:`, err));
|
|
192
|
+
this.recordHit(item.id).catch((err) => console.error(`[KnowledgeDistiller] Failed to record hit for ${item.id}:`, err));
|
|
164
193
|
}
|
|
165
194
|
return filtered;
|
|
166
195
|
}
|
|
@@ -177,14 +206,14 @@ class KnowledgeDistiller {
|
|
|
177
206
|
return;
|
|
178
207
|
const metadata = typeof existing.metadata === 'string'
|
|
179
208
|
? JSON.parse(existing.metadata)
|
|
180
|
-
:
|
|
209
|
+
: existing.metadata || {};
|
|
181
210
|
metadata.hit_count = (metadata.hit_count || 0) + 1;
|
|
182
211
|
metadata.last_retrieved_at = new Date().toISOString();
|
|
183
212
|
await this.db
|
|
184
213
|
.updateTable(this.knowledgeTable)
|
|
185
214
|
.set({
|
|
186
215
|
metadata: JSON.stringify(metadata),
|
|
187
|
-
updated_at: new Date()
|
|
216
|
+
updated_at: new Date(),
|
|
188
217
|
})
|
|
189
218
|
.where('id', '=', id)
|
|
190
219
|
.execute();
|
|
@@ -194,7 +223,7 @@ class KnowledgeDistiller {
|
|
|
194
223
|
.values({
|
|
195
224
|
metric_name: `entity_hit_${existing.entity}`,
|
|
196
225
|
metric_value: 1,
|
|
197
|
-
created_at: new Date()
|
|
226
|
+
created_at: new Date(),
|
|
198
227
|
})
|
|
199
228
|
.execute();
|
|
200
229
|
}
|
|
@@ -211,7 +240,7 @@ class KnowledgeDistiller {
|
|
|
211
240
|
const stn = Math.min(1.0, hitCount / ageInDays);
|
|
212
241
|
// Source Multiplier: User verified facts get 1.0, Assistant-generated 0.7
|
|
213
242
|
const sourceMult = metadata.source === 'user' ? 1.0 : 0.7;
|
|
214
|
-
return
|
|
243
|
+
return item.confidence * 0.4 + stn * 0.4 + sourceMult * 0.2;
|
|
215
244
|
}
|
|
216
245
|
/**
|
|
217
246
|
* Challenge existing knowledge with new evidence.
|
|
@@ -238,12 +267,18 @@ class KnowledgeDistiller {
|
|
|
238
267
|
let newStatus = parsedItem.status;
|
|
239
268
|
if (parsedItem.confidence > 0.7) {
|
|
240
269
|
newStatus = 'disputed';
|
|
241
|
-
newMeta = {
|
|
270
|
+
newMeta = {
|
|
271
|
+
...newMeta,
|
|
272
|
+
status_reason: `Contradicted by: ${competingFact}`,
|
|
273
|
+
};
|
|
242
274
|
penalty = 0.1;
|
|
243
275
|
}
|
|
244
276
|
else {
|
|
245
277
|
newStatus = 'deprecated';
|
|
246
|
-
newMeta = {
|
|
278
|
+
newMeta = {
|
|
279
|
+
...newMeta,
|
|
280
|
+
status_reason: `Superseded by: ${competingFact}`,
|
|
281
|
+
};
|
|
247
282
|
penalty = 0.4;
|
|
248
283
|
}
|
|
249
284
|
const newConfidence = Math.max(0, parsedItem.confidence - penalty);
|
|
@@ -253,7 +288,7 @@ class KnowledgeDistiller {
|
|
|
253
288
|
confidence: newConfidence,
|
|
254
289
|
status: newStatus,
|
|
255
290
|
metadata: JSON.stringify(newMeta),
|
|
256
|
-
updated_at: new Date()
|
|
291
|
+
updated_at: new Date(),
|
|
257
292
|
})
|
|
258
293
|
.where('id', '=', parsedItem.id)
|
|
259
294
|
.execute();
|
|
@@ -266,35 +301,44 @@ class KnowledgeDistiller {
|
|
|
266
301
|
* Production Hardening: Uses batched cross-similarity and NER-style tokenization.
|
|
267
302
|
*/
|
|
268
303
|
async autoLinkKnowledge(item, trx) {
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
304
|
+
// 1. Structural/Syntactic Extraction (NER-style tokenization)
|
|
305
|
+
// Extract capitalized phrases (potential entities), quoted strings, and CamelCase identifiers
|
|
306
|
+
const tokens = item.fact.match(/([A-Z][a-z]+(?:\s[A-Z][a-z]+)*)|("[^"]+")|([a-z]+[A-Z][a-z]+)/g) || [];
|
|
307
|
+
const potentialEntities = Array.from(new Set(tokens.map((t) => t.replace(/"/g, '').trim()))).filter((t) => t.length > 2 && t !== item.entity);
|
|
308
|
+
if (potentialEntities.length > 0) {
|
|
309
|
+
const matches = await trx
|
|
310
|
+
.selectFrom(this.knowledgeTable)
|
|
311
|
+
.select(['id', 'entity'])
|
|
312
|
+
.where('entity', 'in', potentialEntities)
|
|
313
|
+
.execute();
|
|
314
|
+
for (const match of matches) {
|
|
315
|
+
await this.linkKnowledge(item.id, match.id, 'mentions', { auto: true, source: 'structural_extraction' }, trx);
|
|
316
|
+
}
|
|
282
317
|
}
|
|
283
|
-
//
|
|
284
|
-
|
|
318
|
+
// 2. Semantic Similarity Pass (Vector/Cosine Approximation)
|
|
319
|
+
// We limit the search to items with high intrinsic fitness to avoid linking to "noise"
|
|
320
|
+
const candidates = await trx
|
|
285
321
|
.selectFrom(this.knowledgeTable)
|
|
286
322
|
.selectAll()
|
|
287
323
|
.where('id', '!=', item.id)
|
|
324
|
+
.where('confidence', '>', 0.4) // Only link to semi-reliable knowledge
|
|
288
325
|
.orderBy('updated_at', 'desc')
|
|
289
|
-
.limit(
|
|
326
|
+
.limit(50) // Increased limit for better coverage
|
|
290
327
|
.execute();
|
|
291
|
-
|
|
328
|
+
// Batch similarity processing to reduce link churn
|
|
329
|
+
const linksToCreate = [];
|
|
330
|
+
for (const other of candidates) {
|
|
292
331
|
const parsedOther = this.parseKnowledge(other);
|
|
293
332
|
const sim = (0, similarity_js_1.calculateSimilarity)(item.fact, parsedOther.fact);
|
|
294
|
-
|
|
295
|
-
|
|
333
|
+
// High similarity threshold for auto-linking to prevent a "everything linked to everything" graph
|
|
334
|
+
if (sim > 0.75) {
|
|
335
|
+
linksToCreate.push({ targetId: parsedOther.id, sim });
|
|
296
336
|
}
|
|
297
337
|
}
|
|
338
|
+
// Apply links in batch
|
|
339
|
+
for (const link of linksToCreate) {
|
|
340
|
+
await this.linkKnowledge(item.id, link.targetId, 'semantically_related', { similarity: link.sim, version: '2.0' }, trx);
|
|
341
|
+
}
|
|
298
342
|
}
|
|
299
343
|
/**
|
|
300
344
|
* Link two knowledge items together with a relationship.
|
|
@@ -314,7 +358,7 @@ class KnowledgeDistiller {
|
|
|
314
358
|
await trxOrDb
|
|
315
359
|
.updateTable(this.linksTable)
|
|
316
360
|
.set({
|
|
317
|
-
metadata: metadata ? JSON.stringify(metadata) : null
|
|
361
|
+
metadata: metadata ? JSON.stringify(metadata) : null,
|
|
318
362
|
})
|
|
319
363
|
.where('id', '=', existing.id)
|
|
320
364
|
.execute();
|
|
@@ -327,7 +371,7 @@ class KnowledgeDistiller {
|
|
|
327
371
|
target_id: targetId,
|
|
328
372
|
relationship,
|
|
329
373
|
metadata: metadata ? JSON.stringify(metadata) : null,
|
|
330
|
-
created_at: new Date()
|
|
374
|
+
created_at: new Date(),
|
|
331
375
|
})
|
|
332
376
|
.execute();
|
|
333
377
|
}
|
|
@@ -352,10 +396,10 @@ class KnowledgeDistiller {
|
|
|
352
396
|
.execute();
|
|
353
397
|
return {
|
|
354
398
|
item: this.parseKnowledge(center),
|
|
355
|
-
relations: links.map(l => ({
|
|
399
|
+
relations: links.map((l) => ({
|
|
356
400
|
relationship: l.link_rel,
|
|
357
|
-
target: this.parseKnowledge(l)
|
|
358
|
-
}))
|
|
401
|
+
target: this.parseKnowledge(l),
|
|
402
|
+
})),
|
|
359
403
|
};
|
|
360
404
|
}
|
|
361
405
|
/**
|
|
@@ -408,7 +452,7 @@ class KnowledgeDistiller {
|
|
|
408
452
|
...secondary.metadata,
|
|
409
453
|
...primary.metadata,
|
|
410
454
|
consolidated_from: secondary.id,
|
|
411
|
-
consolidated_at: new Date().toISOString()
|
|
455
|
+
consolidated_at: new Date().toISOString(),
|
|
412
456
|
};
|
|
413
457
|
const mergedTags = Array.from(new Set([...(primary.tags || []), ...(secondary.tags || [])]));
|
|
414
458
|
await this.db.transaction().execute(async (trx) => {
|
|
@@ -419,7 +463,7 @@ class KnowledgeDistiller {
|
|
|
419
463
|
confidence: Math.max(primary.confidence, secondary.confidence),
|
|
420
464
|
metadata: JSON.stringify(mergedMeta),
|
|
421
465
|
tags: JSON.stringify(mergedTags),
|
|
422
|
-
updated_at: new Date()
|
|
466
|
+
updated_at: new Date(),
|
|
423
467
|
})
|
|
424
468
|
.where('id', '=', primary.id)
|
|
425
469
|
.execute();
|
|
@@ -430,6 +474,14 @@ class KnowledgeDistiller {
|
|
|
430
474
|
.execute();
|
|
431
475
|
});
|
|
432
476
|
}
|
|
477
|
+
bloomHash(str) {
|
|
478
|
+
let hash = 0;
|
|
479
|
+
for (let i = 0; i < str.length; i++) {
|
|
480
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
481
|
+
hash |= 0; // Format to 32bit int
|
|
482
|
+
}
|
|
483
|
+
return hash;
|
|
484
|
+
}
|
|
433
485
|
parseKnowledge(item) {
|
|
434
486
|
return {
|
|
435
487
|
id: item.id,
|
|
@@ -438,10 +490,12 @@ class KnowledgeDistiller {
|
|
|
438
490
|
confidence: item.confidence,
|
|
439
491
|
status: item.status || 'proposed',
|
|
440
492
|
sourceSessionId: item.source_session_id,
|
|
441
|
-
tags: typeof item.tags === 'string' ? JSON.parse(item.tags) :
|
|
442
|
-
metadata: typeof item.metadata === 'string'
|
|
493
|
+
tags: typeof item.tags === 'string' ? JSON.parse(item.tags) : item.tags || [],
|
|
494
|
+
metadata: typeof item.metadata === 'string'
|
|
495
|
+
? JSON.parse(item.metadata)
|
|
496
|
+
: item.metadata || {},
|
|
443
497
|
createdAt: new Date(item.created_at),
|
|
444
|
-
updatedAt: new Date(item.updated_at)
|
|
498
|
+
updatedAt: new Date(item.updated_at),
|
|
445
499
|
};
|
|
446
500
|
}
|
|
447
501
|
}
|
|
@@ -17,9 +17,15 @@ export declare class RecursiveReasoner {
|
|
|
17
17
|
*/
|
|
18
18
|
analyzeGlobalProgress(pattern: string): Promise<AgentGoal[]>;
|
|
19
19
|
/**
|
|
20
|
-
* Synthesize high-level lessons and cluster similar ones using
|
|
20
|
+
* Synthesize high-level lessons and cluster similar ones using Token-Weighted significance.
|
|
21
|
+
* Pass 5: High-Throughput Semantic Analysis.
|
|
21
22
|
*/
|
|
22
23
|
synthesizeLessons(): Promise<Record<string, string[]>>;
|
|
24
|
+
/**
|
|
25
|
+
* Pass 6: Goal Cross-Pollination
|
|
26
|
+
* Distill successful persona mutations into global systemic goals.
|
|
27
|
+
*/
|
|
28
|
+
crossPollinateGoals(): Promise<number>;
|
|
23
29
|
/**
|
|
24
30
|
* Detect contradictions in goals (e.g., opposing objectives).
|
|
25
31
|
*/
|
|
@@ -16,9 +16,23 @@ class RecursiveReasoner {
|
|
|
16
16
|
['fast', 'slow'],
|
|
17
17
|
['short', 'long'],
|
|
18
18
|
['start', 'stop'],
|
|
19
|
-
['enable', 'disable']
|
|
19
|
+
['enable', 'disable'],
|
|
20
20
|
];
|
|
21
|
-
stopWords = new Set([
|
|
21
|
+
stopWords = new Set([
|
|
22
|
+
'the',
|
|
23
|
+
'a',
|
|
24
|
+
'an',
|
|
25
|
+
'and',
|
|
26
|
+
'or',
|
|
27
|
+
'but',
|
|
28
|
+
'in',
|
|
29
|
+
'on',
|
|
30
|
+
'at',
|
|
31
|
+
'to',
|
|
32
|
+
'for',
|
|
33
|
+
'with',
|
|
34
|
+
'from',
|
|
35
|
+
]);
|
|
22
36
|
constructor(db, config = {}) {
|
|
23
37
|
this.db = db;
|
|
24
38
|
this.config = config;
|
|
@@ -31,48 +45,114 @@ class RecursiveReasoner {
|
|
|
31
45
|
* Find goals matching a pattern across all sessions
|
|
32
46
|
*/
|
|
33
47
|
async analyzeGlobalProgress(pattern) {
|
|
34
|
-
const goals = await this.typedDb
|
|
48
|
+
const goals = (await this.typedDb
|
|
35
49
|
.selectFrom(this.goalsTable)
|
|
36
50
|
.selectAll()
|
|
37
51
|
.where('description', 'like', `%${pattern}%`)
|
|
38
52
|
.orderBy('created_at', 'desc')
|
|
39
|
-
.execute();
|
|
53
|
+
.execute());
|
|
40
54
|
return goals.map(this.parseGoal);
|
|
41
55
|
}
|
|
42
56
|
/**
|
|
43
|
-
* Synthesize high-level lessons and cluster similar ones using
|
|
57
|
+
* Synthesize high-level lessons and cluster similar ones using Token-Weighted significance.
|
|
58
|
+
* Pass 5: High-Throughput Semantic Analysis.
|
|
44
59
|
*/
|
|
45
60
|
async synthesizeLessons() {
|
|
46
|
-
console.log('[RecursiveReasoner]
|
|
61
|
+
console.log('[RecursiveReasoner] Performing high-throughput weighted token clustering...');
|
|
47
62
|
const reflectionsTable = this.config.reflectionsTable || 'agent_reflections';
|
|
48
|
-
const results = await this.typedDb
|
|
63
|
+
const results = (await this.typedDb
|
|
49
64
|
.selectFrom(reflectionsTable)
|
|
50
65
|
.select('lessons_learned')
|
|
51
66
|
.where('lessons_learned', 'is not', null)
|
|
52
|
-
.execute();
|
|
53
|
-
const rawLessons = results
|
|
67
|
+
.execute());
|
|
68
|
+
const rawLessons = results
|
|
69
|
+
.map((l) => l.lessons_learned)
|
|
70
|
+
.filter(Boolean);
|
|
54
71
|
const clusters = {};
|
|
72
|
+
// Global Token Frequency Pass
|
|
73
|
+
const globalTokenFreq = new Map();
|
|
74
|
+
for (const lesson of rawLessons) {
|
|
75
|
+
for (const token of this.tokenize(lesson)) {
|
|
76
|
+
globalTokenFreq.set(token, (globalTokenFreq.get(token) || 0) + 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
55
79
|
for (const lesson of rawLessons) {
|
|
56
80
|
const tokens = this.tokenize(lesson);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
81
|
+
if (tokens.length === 0)
|
|
82
|
+
continue;
|
|
83
|
+
// Weight tokens by (length * global_rarity) to find the most "defining" token
|
|
84
|
+
// Rarity = 1 / Frequency
|
|
85
|
+
const definingToken = tokens.sort((a, b) => {
|
|
86
|
+
const weightA = a.length * (1 / (globalTokenFreq.get(a) || 1));
|
|
87
|
+
const weightB = b.length * (1 / (globalTokenFreq.get(b) || 1));
|
|
88
|
+
return weightB - weightA;
|
|
89
|
+
})[0] || 'general';
|
|
90
|
+
if (!clusters[definingToken]) {
|
|
91
|
+
clusters[definingToken] = [];
|
|
61
92
|
}
|
|
62
|
-
clusters[
|
|
93
|
+
clusters[definingToken].push(lesson);
|
|
63
94
|
}
|
|
64
95
|
return clusters;
|
|
65
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Pass 6: Goal Cross-Pollination
|
|
99
|
+
* Distill successful persona mutations into global systemic goals.
|
|
100
|
+
*/
|
|
101
|
+
async crossPollinateGoals() {
|
|
102
|
+
console.log('[RecursiveReasoner] Cross-pollinating successful persona breakthroughs into global goals...');
|
|
103
|
+
const personasTable = this.config.personasTable || 'agent_personas';
|
|
104
|
+
const goalsTable = this.config.goalsTable || 'agent_goals';
|
|
105
|
+
// Find personas with 'stable' evolution status (proven breakthroughs)
|
|
106
|
+
const breakthroughs = await this.typedDb
|
|
107
|
+
.selectFrom(personasTable)
|
|
108
|
+
.selectAll()
|
|
109
|
+
.where('metadata', 'like', '%"evolution_status":"stable"%')
|
|
110
|
+
.execute();
|
|
111
|
+
let goalsCreated = 0;
|
|
112
|
+
for (const p of breakthroughs) {
|
|
113
|
+
const persona = p;
|
|
114
|
+
const metadata = JSON.parse(persona.metadata || '{}');
|
|
115
|
+
const reasoning = metadata.mutation_reasoning || metadata.reasoning;
|
|
116
|
+
if (!reasoning)
|
|
117
|
+
continue;
|
|
118
|
+
// Check if this goal already exists to avoid duplication
|
|
119
|
+
const existing = await this.typedDb
|
|
120
|
+
.selectFrom(goalsTable)
|
|
121
|
+
.select('id')
|
|
122
|
+
.where('description', 'like', `%${reasoning.slice(0, 50)}%`)
|
|
123
|
+
.executeTakeFirst();
|
|
124
|
+
if (!existing) {
|
|
125
|
+
console.log(`[RecursiveReasoner] Distilling breakthrough from Persona ${persona.id} into Global Goal...`);
|
|
126
|
+
await this.typedDb
|
|
127
|
+
.insertInto(goalsTable)
|
|
128
|
+
.values({
|
|
129
|
+
session_id: 0, // System-level goal
|
|
130
|
+
description: `Systemic Best-Practice: ${reasoning}`,
|
|
131
|
+
status: 'pending',
|
|
132
|
+
priority: 5,
|
|
133
|
+
metadata: JSON.stringify({
|
|
134
|
+
source_persona: persona.id,
|
|
135
|
+
cross_pollinated: true,
|
|
136
|
+
}),
|
|
137
|
+
created_at: new Date(),
|
|
138
|
+
updated_at: new Date(),
|
|
139
|
+
})
|
|
140
|
+
.execute();
|
|
141
|
+
goalsCreated++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return goalsCreated;
|
|
145
|
+
}
|
|
66
146
|
/**
|
|
67
147
|
* Detect contradictions in goals (e.g., opposing objectives).
|
|
68
148
|
*/
|
|
69
149
|
async detectContradictions() {
|
|
70
150
|
console.log('[RecursiveReasoner] Detecting logical contradictions in systemic goals...');
|
|
71
|
-
const activeGoals = await this.typedDb
|
|
151
|
+
const activeGoals = (await this.typedDb
|
|
72
152
|
.selectFrom(this.goalsTable)
|
|
73
153
|
.selectAll()
|
|
74
154
|
.where('status', '=', 'active')
|
|
75
|
-
.execute();
|
|
155
|
+
.execute());
|
|
76
156
|
const contradictions = [];
|
|
77
157
|
for (let i = 0; i < activeGoals.length; i++) {
|
|
78
158
|
for (let j = i + 1; j < activeGoals.length; j++) {
|
|
@@ -97,7 +177,8 @@ class RecursiveReasoner {
|
|
|
97
177
|
const t2 = text2.toLowerCase();
|
|
98
178
|
// Check explicit opposites
|
|
99
179
|
for (const [op1, op2] of this.conflictPairs) {
|
|
100
|
-
if ((t1.includes(op1) && t2.includes(op2)) ||
|
|
180
|
+
if ((t1.includes(op1) && t2.includes(op2)) ||
|
|
181
|
+
(t1.includes(op2) && t2.includes(op1))) {
|
|
101
182
|
// Determine the subject of conflict (common words)
|
|
102
183
|
const intersection = this.intersect(this.tokenize(t1), this.tokenize(t2));
|
|
103
184
|
// If they share a subject (e.g. "latency"), it's a conflict
|
|
@@ -111,13 +192,14 @@ class RecursiveReasoner {
|
|
|
111
192
|
return null;
|
|
112
193
|
}
|
|
113
194
|
tokenize(text) {
|
|
114
|
-
return text
|
|
195
|
+
return text
|
|
196
|
+
.toLowerCase()
|
|
115
197
|
.split(/[\W_]+/)
|
|
116
|
-
.filter(w => w.length > 2 && !this.stopWords.has(w));
|
|
198
|
+
.filter((w) => w.length > 2 && !this.stopWords.has(w));
|
|
117
199
|
}
|
|
118
200
|
intersect(arr1, arr2) {
|
|
119
201
|
const s2 = new Set(arr2);
|
|
120
|
-
return arr1.filter(x => s2.has(x));
|
|
202
|
+
return arr1.filter((x) => s2.has(x));
|
|
121
203
|
}
|
|
122
204
|
parseGoal(g) {
|
|
123
205
|
return {
|
|
@@ -127,9 +209,11 @@ class RecursiveReasoner {
|
|
|
127
209
|
description: g.description,
|
|
128
210
|
status: g.status,
|
|
129
211
|
priority: g.priority,
|
|
130
|
-
metadata: typeof g.metadata === 'string'
|
|
212
|
+
metadata: typeof g.metadata === 'string'
|
|
213
|
+
? JSON.parse(g.metadata)
|
|
214
|
+
: g.metadata || {},
|
|
131
215
|
createdAt: new Date(g.created_at),
|
|
132
|
-
updatedAt: new Date(g.updated_at)
|
|
216
|
+
updatedAt: new Date(g.updated_at),
|
|
133
217
|
};
|
|
134
218
|
}
|
|
135
219
|
}
|
|
@@ -18,31 +18,33 @@ class ReflectionEngine {
|
|
|
18
18
|
* Record a reflection for a session
|
|
19
19
|
*/
|
|
20
20
|
async reflect(sessionId, outcome, lessonsLearned, suggestedActions, metadata) {
|
|
21
|
-
const reflection = await this.db
|
|
21
|
+
const reflection = (await this.db
|
|
22
22
|
.insertInto(this.reflectionsTable)
|
|
23
23
|
.values({
|
|
24
24
|
session_id: sessionId,
|
|
25
25
|
outcome,
|
|
26
26
|
lessons_learned: lessonsLearned,
|
|
27
|
-
suggested_actions: suggestedActions
|
|
27
|
+
suggested_actions: suggestedActions
|
|
28
|
+
? JSON.stringify(suggestedActions)
|
|
29
|
+
: null,
|
|
28
30
|
metadata: metadata ? JSON.stringify(metadata) : null,
|
|
29
|
-
created_at: new Date()
|
|
31
|
+
created_at: new Date(),
|
|
30
32
|
})
|
|
31
33
|
.returningAll()
|
|
32
|
-
.executeTakeFirstOrThrow();
|
|
34
|
+
.executeTakeFirstOrThrow());
|
|
33
35
|
return this.parseReflection(reflection);
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Get reflections for a specific session
|
|
37
39
|
*/
|
|
38
40
|
async getSessionReflections(sessionId) {
|
|
39
|
-
const reflections = await this.db
|
|
41
|
+
const reflections = (await this.db
|
|
40
42
|
.selectFrom(this.reflectionsTable)
|
|
41
43
|
.selectAll()
|
|
42
44
|
.where('session_id', '=', sessionId)
|
|
43
45
|
.orderBy('created_at', 'desc')
|
|
44
|
-
.execute();
|
|
45
|
-
return reflections.map(r => this.parseReflection(r));
|
|
46
|
+
.execute());
|
|
47
|
+
return reflections.map((r) => this.parseReflection(r));
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
50
|
* Get recent lessons learned across all sessions
|
|
@@ -67,7 +69,7 @@ class ReflectionEngine {
|
|
|
67
69
|
metadata: typeof reflection.metadata === 'string'
|
|
68
70
|
? JSON.parse(reflection.metadata)
|
|
69
71
|
: reflection.metadata,
|
|
70
|
-
createdAt: new Date(reflection.created_at)
|
|
72
|
+
createdAt: new Date(reflection.created_at),
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
}
|