noormme 1.1.0 → 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 +84 -65
- package/dist/cjs/agentic/ActionJournal.js +13 -9
- package/dist/cjs/agentic/CapabilityManager.js +35 -21
- package/dist/cjs/agentic/CognitiveRepository.js +19 -9
- package/dist/cjs/agentic/ContextBuffer.js +24 -12
- package/dist/cjs/agentic/Cortex.js +11 -4
- 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.js +30 -9
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +27 -23
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +4 -4
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +16 -6
- 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.js +19 -11
- package/dist/cjs/agentic/improvement/HiveLink.js +22 -15
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +48 -32
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +40 -17
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +28 -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.js +42 -27
- package/dist/cjs/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +120 -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 +5 -2
- 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 +2 -0
- package/dist/cjs/helpers/postgresql.js +7 -4
- package/dist/cjs/helpers/schema-evolution.js +31 -6
- package/dist/cjs/index.d.ts +3 -3
- 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 +52 -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 +5 -2
- 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.js +35 -21
- package/dist/esm/agentic/CognitiveRepository.js +19 -9
- package/dist/esm/agentic/ContextBuffer.js +24 -12
- package/dist/esm/agentic/Cortex.js +11 -4
- 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.js +30 -9
- package/dist/esm/agentic/improvement/CuriosityEngine.js +27 -23
- package/dist/esm/agentic/improvement/EvolutionRitual.js +4 -4
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +16 -6
- 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.js +19 -11
- package/dist/esm/agentic/improvement/HiveLink.js +22 -15
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +48 -32
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +40 -17
- package/dist/esm/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +28 -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.js +42 -27
- package/dist/esm/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/esm/agentic/improvement/StrategicPlanner.js +120 -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 +5 -2
- 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 +2 -0
- package/dist/esm/helpers/postgresql.js +7 -4
- package/dist/esm/helpers/schema-evolution.js +31 -6
- package/dist/esm/index.d.ts +3 -3
- 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 +52 -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 +5 -2
- 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
|
@@ -22,7 +22,7 @@ class RuleEngine {
|
|
|
22
22
|
*/
|
|
23
23
|
async defineRule(tableName, operation, action, options = {}) {
|
|
24
24
|
return await this.db.transaction().execute(async (trx) => {
|
|
25
|
-
const rule = await trx
|
|
25
|
+
const rule = (await trx
|
|
26
26
|
.insertInto(this.rulesTable)
|
|
27
27
|
.values({
|
|
28
28
|
table_name: tableName,
|
|
@@ -33,10 +33,10 @@ class RuleEngine {
|
|
|
33
33
|
script: options.script || null,
|
|
34
34
|
is_enabled: true,
|
|
35
35
|
metadata: options.metadata ? JSON.stringify(options.metadata) : null,
|
|
36
|
-
created_at: new Date()
|
|
36
|
+
created_at: new Date(),
|
|
37
37
|
})
|
|
38
38
|
.returningAll()
|
|
39
|
-
.executeTakeFirstOrThrow();
|
|
39
|
+
.executeTakeFirstOrThrow());
|
|
40
40
|
return this.parseRule(rule);
|
|
41
41
|
});
|
|
42
42
|
}
|
|
@@ -53,7 +53,7 @@ class RuleEngine {
|
|
|
53
53
|
return {
|
|
54
54
|
action: rule.action,
|
|
55
55
|
ruleId: rule.id,
|
|
56
|
-
reason: `Matched rule ${rule.id} (${rule.action})
|
|
56
|
+
reason: `Matched rule ${rule.id} (${rule.action})`,
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -82,13 +82,10 @@ class RuleEngine {
|
|
|
82
82
|
.selectFrom(this.rulesTable)
|
|
83
83
|
.selectAll()
|
|
84
84
|
.where('table_name', '=', tableName)
|
|
85
|
-
.where((eb) => eb.or([
|
|
86
|
-
eb('operation', '=', operation),
|
|
87
|
-
eb('operation', '=', 'all')
|
|
88
|
-
]))
|
|
85
|
+
.where((eb) => eb.or([eb('operation', '=', operation), eb('operation', '=', 'all')]))
|
|
89
86
|
.where('is_enabled', '=', true)
|
|
90
87
|
.execute();
|
|
91
|
-
return list.map(r => this.parseRule(r));
|
|
88
|
+
return list.map((r) => this.parseRule(r));
|
|
92
89
|
}
|
|
93
90
|
evaluateCondition(condition, data) {
|
|
94
91
|
// Simple condition parser: "key op value"
|
|
@@ -107,12 +104,18 @@ class RuleEngine {
|
|
|
107
104
|
if (compareValue === 'false')
|
|
108
105
|
compareValue = false;
|
|
109
106
|
switch (op) {
|
|
110
|
-
case '==':
|
|
111
|
-
|
|
112
|
-
case '
|
|
113
|
-
|
|
114
|
-
case '
|
|
115
|
-
|
|
107
|
+
case '==':
|
|
108
|
+
return val == compareValue;
|
|
109
|
+
case '!=':
|
|
110
|
+
return val != compareValue;
|
|
111
|
+
case '>':
|
|
112
|
+
return val > compareValue;
|
|
113
|
+
case '<':
|
|
114
|
+
return val < compareValue;
|
|
115
|
+
case 'includes':
|
|
116
|
+
return String(val).includes(String(compareValue));
|
|
117
|
+
default:
|
|
118
|
+
return false;
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
parseRule(r) {
|
|
@@ -124,8 +127,10 @@ class RuleEngine {
|
|
|
124
127
|
action: r.action,
|
|
125
128
|
priority: r.priority,
|
|
126
129
|
isEnabled: !!r.is_enabled,
|
|
127
|
-
metadata: typeof r.metadata === 'string'
|
|
128
|
-
|
|
130
|
+
metadata: typeof r.metadata === 'string'
|
|
131
|
+
? JSON.parse(r.metadata)
|
|
132
|
+
: r.metadata || {},
|
|
133
|
+
createdAt: new Date(r.created_at),
|
|
129
134
|
};
|
|
130
135
|
}
|
|
131
136
|
}
|
|
@@ -54,7 +54,8 @@ class SelfEvolution {
|
|
|
54
54
|
this.config = config;
|
|
55
55
|
this.evolution = new schema_evolution_js_1.SchemaEvolutionHelper(db);
|
|
56
56
|
this.typeGenerator = new type_generator_js_1.TypeGenerator(config.introspection);
|
|
57
|
-
this.snapshotsTable =
|
|
57
|
+
this.snapshotsTable =
|
|
58
|
+
config.agentic?.metadata?.snapshotsTable || 'agent_snapshots';
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Ensure core agentic tables have telemetry columns like 'accessed_at'
|
|
@@ -65,13 +66,16 @@ class SelfEvolution {
|
|
|
65
66
|
this.config.agentic?.messagesTable || 'agent_messages',
|
|
66
67
|
this.config.agentic?.memoriesTable || 'agent_memories',
|
|
67
68
|
this.config.agentic?.goalsTable || 'agent_goals',
|
|
68
|
-
this.config.agentic?.knowledgeTable || 'agent_knowledge_base'
|
|
69
|
+
this.config.agentic?.knowledgeTable || 'agent_knowledge_base',
|
|
69
70
|
];
|
|
70
71
|
for (const table of tables) {
|
|
71
72
|
try {
|
|
72
73
|
const introspector = this.db.introspection;
|
|
73
|
-
const tableInfo = await introspector
|
|
74
|
-
|
|
74
|
+
const tableInfo = await introspector
|
|
75
|
+
.getTables()
|
|
76
|
+
.then((ts) => ts.find((t) => t.name === table));
|
|
77
|
+
if (tableInfo &&
|
|
78
|
+
!tableInfo.columns.some((c) => c.name === 'accessed_at')) {
|
|
75
79
|
console.log(`[SelfEvolution] Adding 'accessed_at' column to ${table}`);
|
|
76
80
|
await (0, sql_js_1.sql) `ALTER TABLE ${sql_js_1.sql.table(table)} ADD COLUMN accessed_at TIMESTAMP`.execute(this.db);
|
|
77
81
|
}
|
|
@@ -142,9 +146,9 @@ class SelfEvolution {
|
|
|
142
146
|
...options.metadata,
|
|
143
147
|
ddl,
|
|
144
148
|
is_auto: true,
|
|
145
|
-
timestamp: Date.now()
|
|
149
|
+
timestamp: Date.now(),
|
|
146
150
|
}),
|
|
147
|
-
created_at: new Date()
|
|
151
|
+
created_at: new Date(),
|
|
148
152
|
})
|
|
149
153
|
.execute();
|
|
150
154
|
// 2. Regenerate types
|
|
@@ -158,13 +162,13 @@ class SelfEvolution {
|
|
|
158
162
|
const introspector = this.db.introspection;
|
|
159
163
|
const tables = await introspector.getTables();
|
|
160
164
|
const schemaInfo = {
|
|
161
|
-
tables: tables.map(t => ({
|
|
165
|
+
tables: tables.map((t) => ({
|
|
162
166
|
name: t.name,
|
|
163
167
|
columns: t.columns || [],
|
|
164
168
|
indexes: t.indexes || [],
|
|
165
|
-
foreignKeys: t.foreignKeys || []
|
|
169
|
+
foreignKeys: t.foreignKeys || [],
|
|
166
170
|
})),
|
|
167
|
-
relationships: []
|
|
171
|
+
relationships: [],
|
|
168
172
|
};
|
|
169
173
|
const generated = this.typeGenerator.generateTypes(schemaInfo);
|
|
170
174
|
if (this.config.agentic?.metadata?.typesOutputPath) {
|
|
@@ -188,12 +192,12 @@ class SelfEvolution {
|
|
|
188
192
|
if (ctx.includes('slow') || ctx.includes('latency')) {
|
|
189
193
|
// Suggest index for metrics if they seem slow
|
|
190
194
|
if (ctx.includes('metrics')) {
|
|
191
|
-
await this.evolve(
|
|
195
|
+
await this.evolve('CREATE INDEX IF NOT EXISTS idx_metrics_fast_lookup ON agent_metrics(metric_name, created_at)');
|
|
192
196
|
return true;
|
|
193
197
|
}
|
|
194
198
|
// Suggest index for memories if semantic search is mentioned
|
|
195
199
|
if (ctx.includes('search') || ctx.includes('memory')) {
|
|
196
|
-
await this.evolve(
|
|
200
|
+
await this.evolve('CREATE INDEX IF NOT EXISTS idx_memories_session_time ON agent_memories(session_id, created_at)');
|
|
197
201
|
return true;
|
|
198
202
|
}
|
|
199
203
|
}
|
|
@@ -203,16 +207,16 @@ class SelfEvolution {
|
|
|
203
207
|
* Get history of evolutions
|
|
204
208
|
*/
|
|
205
209
|
async getEvolutionHistory(limit = 10) {
|
|
206
|
-
const list = await this.db
|
|
210
|
+
const list = (await this.db
|
|
207
211
|
.selectFrom(this.snapshotsTable)
|
|
208
212
|
.selectAll()
|
|
209
213
|
.orderBy('created_at', 'desc')
|
|
210
214
|
.limit(limit)
|
|
211
|
-
.execute();
|
|
212
|
-
return list.map(s => ({
|
|
215
|
+
.execute());
|
|
216
|
+
return list.map((s) => ({
|
|
213
217
|
...s,
|
|
214
218
|
metadata: typeof s.metadata === 'string' ? JSON.parse(s.metadata) : s.metadata,
|
|
215
|
-
createdAt: new Date(s.createdAt)
|
|
219
|
+
createdAt: new Date(s.createdAt),
|
|
216
220
|
}));
|
|
217
221
|
}
|
|
218
222
|
/**
|
|
@@ -220,14 +224,16 @@ class SelfEvolution {
|
|
|
220
224
|
*/
|
|
221
225
|
async rollbackToSnapshot(name) {
|
|
222
226
|
console.log(`[SelfEvolution] Initiating structural rollback to: ${name}`);
|
|
223
|
-
const snapshot = await this.db
|
|
227
|
+
const snapshot = (await this.db
|
|
224
228
|
.selectFrom(this.snapshotsTable)
|
|
225
229
|
.selectAll()
|
|
226
230
|
.where('name', '=', name)
|
|
227
|
-
.executeTakeFirst();
|
|
231
|
+
.executeTakeFirst());
|
|
228
232
|
if (!snapshot)
|
|
229
233
|
throw new Error(`Snapshot ${name} not found.`);
|
|
230
|
-
const metadata = typeof snapshot.metadata === 'string'
|
|
234
|
+
const metadata = typeof snapshot.metadata === 'string'
|
|
235
|
+
? JSON.parse(snapshot.metadata)
|
|
236
|
+
: snapshot.metadata || {};
|
|
231
237
|
if (metadata.ddl) {
|
|
232
238
|
const inverse = this.invertDDL(metadata.ddl);
|
|
233
239
|
if (inverse) {
|
|
@@ -25,11 +25,11 @@ class SelfTestRegistry {
|
|
|
25
25
|
name,
|
|
26
26
|
script,
|
|
27
27
|
expected_outcome: expectedOutcome,
|
|
28
|
-
created_at: new Date()
|
|
28
|
+
created_at: new Date(),
|
|
29
29
|
})
|
|
30
30
|
.onConflict((oc) => oc.column('name').doUpdateSet({
|
|
31
31
|
script,
|
|
32
|
-
expected_outcome: expectedOutcome
|
|
32
|
+
expected_outcome: expectedOutcome,
|
|
33
33
|
}))
|
|
34
34
|
.execute();
|
|
35
35
|
}
|
|
@@ -37,10 +37,10 @@ class SelfTestRegistry {
|
|
|
37
37
|
* Run all registered probes
|
|
38
38
|
*/
|
|
39
39
|
async runAllProbes() {
|
|
40
|
-
const probes = await this.db
|
|
40
|
+
const probes = (await this.db
|
|
41
41
|
.selectFrom('agent_logic_probes')
|
|
42
42
|
.selectAll()
|
|
43
|
-
.execute();
|
|
43
|
+
.execute());
|
|
44
44
|
const results = [];
|
|
45
45
|
for (const probe of probes) {
|
|
46
46
|
console.log(`[SelfTestRegistry] Running probe: ${probe.name}`);
|
|
@@ -61,9 +61,9 @@ class SelfTestRegistry {
|
|
|
61
61
|
this.config.memoriesTable || 'agent_memories',
|
|
62
62
|
this.config.knowledgeTable || 'agent_knowledge_base',
|
|
63
63
|
this.config.actionsTable || 'agent_actions',
|
|
64
|
-
this.config.metricsTable || 'agent_metrics'
|
|
64
|
+
this.config.metricsTable || 'agent_metrics',
|
|
65
65
|
];
|
|
66
|
-
const missing = requiredSubsets.filter(req => !tables.some(t => t.name === req));
|
|
66
|
+
const missing = requiredSubsets.filter((req) => !tables.some((t) => t.name === req));
|
|
67
67
|
success = missing.length === 0;
|
|
68
68
|
break;
|
|
69
69
|
case 'check_memory_integrity':
|
|
@@ -96,47 +96,50 @@ class SelfTestRegistry {
|
|
|
96
96
|
const orphanedKnowledge = await this.db
|
|
97
97
|
.selectFrom(knowledgeTable)
|
|
98
98
|
.where('source_session_id', 'is not', null)
|
|
99
|
-
.where((eb) => eb.not(eb.exists(eb
|
|
99
|
+
.where((eb) => eb.not(eb.exists(eb
|
|
100
|
+
.selectFrom(sessionsTbl)
|
|
100
101
|
.select('id')
|
|
101
102
|
.whereRef(`${knowledgeTable}.source_session_id`, '=', `${sessionsTbl}.id`))))
|
|
102
103
|
.execute();
|
|
103
104
|
const orphanedActions = await this.db
|
|
104
105
|
.selectFrom(actionsTable)
|
|
105
|
-
.where((eb) => eb.not(eb.exists(eb
|
|
106
|
+
.where((eb) => eb.not(eb.exists(eb
|
|
107
|
+
.selectFrom(sessionsTbl)
|
|
106
108
|
.select('id')
|
|
107
109
|
.whereRef(`${actionsTable}.session_id`, '=', `${sessionsTbl}.id`))))
|
|
108
110
|
.execute();
|
|
109
|
-
success =
|
|
111
|
+
success =
|
|
112
|
+
orphanedKnowledge.length === 0 && orphanedActions.length === 0;
|
|
110
113
|
break;
|
|
111
114
|
case 'check_performance_drift':
|
|
112
115
|
// Real check: Compare last 10 queries average with historical baseline
|
|
113
116
|
const metricsTbl = this.config.metricsTable || 'agent_metrics';
|
|
114
|
-
const recentMetrics = await this.db
|
|
117
|
+
const recentMetrics = (await this.db
|
|
115
118
|
.selectFrom(metricsTbl)
|
|
116
119
|
.select('execution_time')
|
|
117
120
|
.orderBy('created_at', 'desc')
|
|
118
121
|
.limit(20)
|
|
119
|
-
.execute();
|
|
122
|
+
.execute());
|
|
120
123
|
if (recentMetrics.length < 5) {
|
|
121
124
|
success = true; // Not enough data to determine drift
|
|
122
125
|
}
|
|
123
126
|
else {
|
|
124
127
|
const avgRecent = recentMetrics.reduce((sum, m) => sum + (m.execution_time || 0), 0) / recentMetrics.length;
|
|
125
128
|
// Baseline: Avg of previous 100 metrics excluding the most recent 20
|
|
126
|
-
const baselineMetrics = await this.db
|
|
129
|
+
const baselineMetrics = (await this.db
|
|
127
130
|
.selectFrom(metricsTbl)
|
|
128
131
|
.select('execution_time')
|
|
129
132
|
.orderBy('created_at', 'desc')
|
|
130
133
|
.offset(20)
|
|
131
134
|
.limit(100)
|
|
132
|
-
.execute();
|
|
135
|
+
.execute());
|
|
133
136
|
if (baselineMetrics.length === 0) {
|
|
134
137
|
success = avgRecent < 500; // Fallback threshold (500ms)
|
|
135
138
|
}
|
|
136
139
|
else {
|
|
137
140
|
const avgBaseline = baselineMetrics.reduce((sum, m) => sum + (m.execution_time || 0), 0) / baselineMetrics.length;
|
|
138
141
|
// Fail if recent performance is > 50% worse than baseline
|
|
139
|
-
success = avgRecent <
|
|
142
|
+
success = avgRecent < avgBaseline * 1.5;
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
break;
|
|
@@ -153,7 +156,7 @@ class SelfTestRegistry {
|
|
|
153
156
|
.updateTable('agent_logic_probes')
|
|
154
157
|
.set({
|
|
155
158
|
last_run: new Date(),
|
|
156
|
-
last_status: success ? 'pass' : 'fail'
|
|
159
|
+
last_status: success ? 'pass' : 'fail',
|
|
157
160
|
})
|
|
158
161
|
.where('id', '=', probe.id)
|
|
159
162
|
.execute();
|
|
@@ -25,15 +25,16 @@ class AISynthesisStrategy {
|
|
|
25
25
|
if (!model) {
|
|
26
26
|
console.warn(`[SkillSynthesizer] No LLMProvider available. Skipping synthesis.`);
|
|
27
27
|
return {
|
|
28
|
-
mutatedDescription: context.existingDescription ||
|
|
28
|
+
mutatedDescription: context.existingDescription ||
|
|
29
|
+
'Unmodified skill (Synthesis skipped: No LLM)',
|
|
29
30
|
mutatedMetadata: { synthesis_status: 'skipped_no_llm' },
|
|
30
|
-
version: `1.0.${Date.now()}
|
|
31
|
+
version: `1.0.${Date.now()}`,
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
34
|
const response = await model.complete({
|
|
34
35
|
prompt,
|
|
35
36
|
responseFormat: 'json',
|
|
36
|
-
temperature: 0.3
|
|
37
|
+
temperature: 0.3,
|
|
37
38
|
});
|
|
38
39
|
if (response.usage) {
|
|
39
40
|
this.synthesizer.totalTokensConsumed += response.usage.totalTokens;
|
|
@@ -44,10 +45,12 @@ class AISynthesisStrategy {
|
|
|
44
45
|
mutatedDescription: parsed.description || context.existingDescription,
|
|
45
46
|
mutatedMetadata: {
|
|
46
47
|
...parsed.metadata,
|
|
47
|
-
synthesis_engine: this.cortex.llmPremium
|
|
48
|
-
|
|
48
|
+
synthesis_engine: this.cortex.llmPremium
|
|
49
|
+
? 'Tiered-Premium'
|
|
50
|
+
: 'Production-LLM',
|
|
51
|
+
failure_context_size: context.failures.length,
|
|
49
52
|
},
|
|
50
|
-
version: `1.0.${Date.now()}
|
|
53
|
+
version: `1.0.${Date.now()}`,
|
|
51
54
|
};
|
|
52
55
|
}
|
|
53
56
|
catch (err) {
|
|
@@ -58,7 +61,7 @@ class AISynthesisStrategy {
|
|
|
58
61
|
attempts++;
|
|
59
62
|
if (attempts >= maxRetries)
|
|
60
63
|
throw error;
|
|
61
|
-
await new Promise(resolve => setTimeout(resolve, 1000 * attempts));
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * attempts));
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
throw new Error('Synthesis failed after maximum retries');
|
|
@@ -74,12 +77,14 @@ class AISynthesisStrategy {
|
|
|
74
77
|
You are a Meta-Evolutionary AI Engine optimizing multiple tools in parallel.
|
|
75
78
|
|
|
76
79
|
TOOLS TO MUTATE:
|
|
77
|
-
${contexts
|
|
80
|
+
${contexts
|
|
81
|
+
.map((ctx, i) => `
|
|
78
82
|
[Tool ${i + 1}: ${ctx.targetTool}]
|
|
79
83
|
Current Description: ${ctx.existingDescription || 'None'}
|
|
80
84
|
Failure Patterns:
|
|
81
|
-
${ctx.failures.map(f => `- Args: ${JSON.stringify(f.arguments)}, Error: ${f.error}`).join('\n')}
|
|
82
|
-
`)
|
|
85
|
+
${ctx.failures.map((f) => `- Args: ${JSON.stringify(f.arguments)}, Error: ${f.error}`).join('\n')}
|
|
86
|
+
`)
|
|
87
|
+
.join('\n')}
|
|
83
88
|
|
|
84
89
|
TASK:
|
|
85
90
|
For each tool, provide a mutation as a JSON array of objects:
|
|
@@ -95,20 +100,20 @@ class AISynthesisStrategy {
|
|
|
95
100
|
const response = await model.complete({
|
|
96
101
|
prompt: batchPrompt,
|
|
97
102
|
responseFormat: 'json',
|
|
98
|
-
temperature: 0.2
|
|
103
|
+
temperature: 0.2,
|
|
99
104
|
});
|
|
100
105
|
if (response.usage) {
|
|
101
106
|
this.synthesizer.totalTokensConsumed += response.usage.totalTokens;
|
|
102
107
|
}
|
|
103
108
|
try {
|
|
104
109
|
const parsed = JSON.parse(response.content);
|
|
105
|
-
return parsed.map(item => ({
|
|
110
|
+
return parsed.map((item) => ({
|
|
106
111
|
tool: item.tool,
|
|
107
112
|
mutation: {
|
|
108
113
|
mutatedDescription: item.description,
|
|
109
114
|
mutatedMetadata: item.metadata,
|
|
110
|
-
version: `1.0.${Date.now()}
|
|
111
|
-
}
|
|
115
|
+
version: `1.0.${Date.now()}`,
|
|
116
|
+
},
|
|
112
117
|
}));
|
|
113
118
|
}
|
|
114
119
|
catch (err) {
|
|
@@ -116,7 +121,9 @@ class AISynthesisStrategy {
|
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
123
|
buildMutationPrompt(context) {
|
|
119
|
-
const failureList = context.failures
|
|
124
|
+
const failureList = context.failures
|
|
125
|
+
.map((f, i) => `${i + 1}. Args: ${JSON.stringify(f.arguments)}, Error: ${f.error || 'None'}`)
|
|
126
|
+
.join('\n');
|
|
120
127
|
return `
|
|
121
128
|
You are a Meta-Evolutionary AI Engine optimizing a tool: "${context.targetTool}".
|
|
122
129
|
Analyze FAILURES and rewrite the description to prevent them.
|
|
@@ -149,7 +156,7 @@ class SkillSynthesizer {
|
|
|
149
156
|
rollbackThresholdZ: 2.5,
|
|
150
157
|
enableHiveLink: true,
|
|
151
158
|
mutationAggressiveness: 0.5,
|
|
152
|
-
maxSandboxSkills: 5
|
|
159
|
+
maxSandboxSkills: 5,
|
|
153
160
|
};
|
|
154
161
|
this.actionsTable = config.actionsTable || 'agent_actions';
|
|
155
162
|
this.strategy = new AISynthesisStrategy(this.cortex, this);
|
|
@@ -160,7 +167,7 @@ class SkillSynthesizer {
|
|
|
160
167
|
*/
|
|
161
168
|
async preWarmSkill(name) {
|
|
162
169
|
const capability = await this.cortex.capabilities.getCapabilities('experimental');
|
|
163
|
-
const target = capability.find(c => c.name === name);
|
|
170
|
+
const target = capability.find((c) => c.name === name);
|
|
164
171
|
if (!target)
|
|
165
172
|
return;
|
|
166
173
|
// Synthesis pre-run to ensure 'Verified' description is optimized before status change
|
|
@@ -168,14 +175,19 @@ class SkillSynthesizer {
|
|
|
168
175
|
targetTool: target.name,
|
|
169
176
|
failures: [], // No recent failures, just optimizing for permanence
|
|
170
177
|
existingDescription: target.description,
|
|
171
|
-
evolutionConfig: this.evolutionConfig
|
|
178
|
+
evolutionConfig: this.evolutionConfig,
|
|
172
179
|
});
|
|
173
180
|
await this.db
|
|
174
|
-
.updateTable(this.cortex.agenticConfig.capabilitiesTable ||
|
|
181
|
+
.updateTable(this.cortex.agenticConfig.capabilitiesTable ||
|
|
182
|
+
'agent_capabilities')
|
|
175
183
|
.set({
|
|
176
184
|
description: mutation.mutatedDescription,
|
|
177
|
-
metadata: JSON.stringify({
|
|
178
|
-
|
|
185
|
+
metadata: JSON.stringify({
|
|
186
|
+
...target.metadata,
|
|
187
|
+
pre_warmed: true,
|
|
188
|
+
pre_warmed_at: new Date(),
|
|
189
|
+
}),
|
|
190
|
+
updated_at: new Date(),
|
|
179
191
|
})
|
|
180
192
|
.where('name', '=', name)
|
|
181
193
|
.execute();
|
|
@@ -218,12 +230,14 @@ class SkillSynthesizer {
|
|
|
218
230
|
const contexts = await Promise.all(items.map(async (item) => {
|
|
219
231
|
return {
|
|
220
232
|
targetTool: item.tool,
|
|
221
|
-
failures: item.failures.map(f => ({
|
|
222
|
-
arguments: typeof f.arguments === 'string'
|
|
233
|
+
failures: item.failures.map((f) => ({
|
|
234
|
+
arguments: typeof f.arguments === 'string'
|
|
235
|
+
? JSON.parse(f.arguments)
|
|
236
|
+
: f.arguments,
|
|
223
237
|
error: f.outcome,
|
|
224
|
-
timestamp: new Date(f.created_at)
|
|
238
|
+
timestamp: new Date(f.created_at),
|
|
225
239
|
})),
|
|
226
|
-
evolutionConfig: this.evolutionConfig
|
|
240
|
+
evolutionConfig: this.evolutionConfig,
|
|
227
241
|
};
|
|
228
242
|
}));
|
|
229
243
|
if (items.length > 1 && (this.cortex.llmFast || this.cortex.llm)) {
|
|
@@ -251,7 +265,7 @@ class SkillSynthesizer {
|
|
|
251
265
|
mutatedFrom: tool,
|
|
252
266
|
synthesis_engine: 'Ultra-Scale-Tiered',
|
|
253
267
|
...mutation.mutatedMetadata,
|
|
254
|
-
synthesized_at: new Date()
|
|
268
|
+
synthesized_at: new Date(),
|
|
255
269
|
});
|
|
256
270
|
}
|
|
257
271
|
async pruneSandboxIfNeeded() {
|
|
@@ -263,7 +277,8 @@ class SkillSynthesizer {
|
|
|
263
277
|
.slice(0, Math.ceil(experimental.length * 0.2));
|
|
264
278
|
for (const skill of toPrune) {
|
|
265
279
|
await this.db
|
|
266
|
-
.deleteFrom(this.cortex.agenticConfig.capabilitiesTable ||
|
|
280
|
+
.deleteFrom(this.cortex.agenticConfig.capabilitiesTable ||
|
|
281
|
+
'agent_capabilities')
|
|
267
282
|
.where('id', '=', skill.id)
|
|
268
283
|
.execute();
|
|
269
284
|
}
|
|
@@ -21,7 +21,7 @@ class SovereignMetrics {
|
|
|
21
21
|
* Record a metric point
|
|
22
22
|
*/
|
|
23
23
|
async recordMetric(metricName, metricValue, options = {}) {
|
|
24
|
-
const metric = await this.db
|
|
24
|
+
const metric = (await this.db
|
|
25
25
|
.insertInto(this.metricsTable)
|
|
26
26
|
.values({
|
|
27
27
|
session_id: options.sessionId ?? null,
|
|
@@ -30,10 +30,10 @@ class SovereignMetrics {
|
|
|
30
30
|
metric_value: metricValue,
|
|
31
31
|
unit: options.unit ?? null,
|
|
32
32
|
metadata: options.metadata ? JSON.stringify(options.metadata) : null,
|
|
33
|
-
created_at: new Date()
|
|
33
|
+
created_at: new Date(),
|
|
34
34
|
})
|
|
35
35
|
.returningAll()
|
|
36
|
-
.executeTakeFirstOrThrow();
|
|
36
|
+
.executeTakeFirstOrThrow());
|
|
37
37
|
return this.parseMetric(metric);
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
@@ -57,7 +57,7 @@ class SovereignMetrics {
|
|
|
57
57
|
eb.fn.min('metric_value').as('min'),
|
|
58
58
|
eb.fn.max('metric_value').as('max'),
|
|
59
59
|
eb.fn.avg('metric_value').as('avg'),
|
|
60
|
-
eb.fn.count('id').as('count')
|
|
60
|
+
eb.fn.count('id').as('count'),
|
|
61
61
|
])
|
|
62
62
|
.where('metric_name', '=', metricName);
|
|
63
63
|
if (options.agentId) {
|
|
@@ -66,51 +66,51 @@ class SovereignMetrics {
|
|
|
66
66
|
if (options.sessionId) {
|
|
67
67
|
query = query.where('session_id', '=', options.sessionId);
|
|
68
68
|
}
|
|
69
|
-
const result = await query.executeTakeFirst();
|
|
69
|
+
const result = (await query.executeTakeFirst());
|
|
70
70
|
return {
|
|
71
71
|
min: Number(result?.min || 0),
|
|
72
72
|
max: Number(result?.max || 0),
|
|
73
73
|
avg: Number(result?.avg || 0),
|
|
74
|
-
count: Number(result?.count || 0)
|
|
74
|
+
count: Number(result?.count || 0),
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
78
|
* Get recent metrics for analysis
|
|
79
79
|
*/
|
|
80
80
|
async getRecentMetrics(limit = 50) {
|
|
81
|
-
const list = await this.typedDb
|
|
81
|
+
const list = (await this.typedDb
|
|
82
82
|
.selectFrom(this.metricsTable)
|
|
83
83
|
.selectAll()
|
|
84
84
|
.orderBy('created_at', 'desc')
|
|
85
85
|
.limit(limit)
|
|
86
|
-
.execute();
|
|
87
|
-
return list.map(m => this.parseMetric(m));
|
|
86
|
+
.execute());
|
|
87
|
+
return list.map((m) => this.parseMetric(m));
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Get metrics filtered by agent ID.
|
|
91
91
|
*/
|
|
92
92
|
async getMetricsByAgent(agentId, limit = 50) {
|
|
93
|
-
const list = await this.typedDb
|
|
93
|
+
const list = (await this.typedDb
|
|
94
94
|
.selectFrom(this.metricsTable)
|
|
95
95
|
.selectAll()
|
|
96
96
|
.where('agent_id', '=', agentId)
|
|
97
97
|
.orderBy('created_at', 'desc')
|
|
98
98
|
.limit(limit)
|
|
99
|
-
.execute();
|
|
100
|
-
return list.map(m => this.parseMetric(m));
|
|
99
|
+
.execute());
|
|
100
|
+
return list.map((m) => this.parseMetric(m));
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Get metrics filtered by session ID.
|
|
104
104
|
*/
|
|
105
105
|
async getMetricsBySession(sessionId, limit = 50) {
|
|
106
|
-
const list = await this.typedDb
|
|
106
|
+
const list = (await this.typedDb
|
|
107
107
|
.selectFrom(this.metricsTable)
|
|
108
108
|
.selectAll()
|
|
109
109
|
.where('session_id', '=', sessionId)
|
|
110
110
|
.orderBy('created_at', 'desc')
|
|
111
111
|
.limit(limit)
|
|
112
|
-
.execute();
|
|
113
|
-
return list.map(m => this.parseMetric(m));
|
|
112
|
+
.execute());
|
|
113
|
+
return list.map((m) => this.parseMetric(m));
|
|
114
114
|
}
|
|
115
115
|
parseMetric(m) {
|
|
116
116
|
return {
|
|
@@ -120,8 +120,10 @@ class SovereignMetrics {
|
|
|
120
120
|
metricName: m.metric_name,
|
|
121
121
|
metricValue: m.metric_value,
|
|
122
122
|
unit: m.unit,
|
|
123
|
-
metadata: typeof m.metadata === 'string'
|
|
124
|
-
|
|
123
|
+
metadata: typeof m.metadata === 'string'
|
|
124
|
+
? JSON.parse(m.metadata)
|
|
125
|
+
: m.metadata || {},
|
|
126
|
+
createdAt: new Date(m.created_at),
|
|
125
127
|
};
|
|
126
128
|
}
|
|
127
129
|
}
|