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