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