noormme 1.2.0 → 1.2.2
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 +60 -6
- package/dist/cjs/agentic/ActionJournal.d.ts +5 -2
- package/dist/cjs/agentic/ActionJournal.js +13 -5
- package/dist/cjs/agentic/CapabilityManager.d.ts +7 -0
- package/dist/cjs/agentic/CapabilityManager.js +84 -7
- package/dist/cjs/agentic/CognitiveRepository.js +3 -6
- package/dist/cjs/agentic/Cortex.d.ts +4 -0
- package/dist/cjs/agentic/Cortex.js +38 -17
- package/dist/cjs/agentic/EpisodicMemory.d.ts +5 -1
- package/dist/cjs/agentic/EpisodicMemory.js +11 -4
- package/dist/cjs/agentic/PersonaManager.js +37 -31
- package/dist/cjs/agentic/PolicyEnforcer.d.ts +6 -1
- package/dist/cjs/agentic/PolicyEnforcer.js +74 -17
- package/dist/cjs/agentic/ResourceMonitor.d.ts +9 -0
- package/dist/cjs/agentic/ResourceMonitor.js +36 -2
- package/dist/cjs/agentic/SessionManager.js +24 -17
- package/dist/cjs/agentic/VectorIndexer.d.ts +1 -0
- package/dist/cjs/agentic/VectorIndexer.js +26 -17
- package/dist/cjs/agentic/improvement/AblationEngine.d.ts +4 -6
- package/dist/cjs/agentic/improvement/AblationEngine.js +57 -37
- package/dist/cjs/agentic/improvement/ActionRefiner.js +30 -14
- package/dist/cjs/agentic/improvement/ConflictResolver.d.ts +3 -1
- package/dist/cjs/agentic/improvement/ConflictResolver.js +59 -47
- package/dist/cjs/agentic/improvement/CortexJanitor.js +11 -0
- package/dist/cjs/agentic/improvement/CuriosityEngine.d.ts +1 -1
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +48 -21
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +26 -14
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +16 -4
- package/dist/cjs/agentic/improvement/GoalArchitect.d.ts +6 -2
- package/dist/cjs/agentic/improvement/GoalArchitect.js +72 -34
- package/dist/cjs/agentic/improvement/GovernanceManager.d.ts +20 -6
- package/dist/cjs/agentic/improvement/GovernanceManager.js +134 -155
- package/dist/cjs/agentic/improvement/HiveLink.d.ts +7 -3
- package/dist/cjs/agentic/improvement/HiveLink.js +135 -113
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +43 -35
- package/dist/cjs/agentic/improvement/QuotaManager.d.ts +41 -0
- package/dist/cjs/agentic/improvement/QuotaManager.js +185 -0
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +50 -25
- package/dist/cjs/agentic/improvement/ReflectionEngine.d.ts +4 -1
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +3 -1
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +27 -16
- package/dist/cjs/agentic/improvement/RuleEngine.d.ts +1 -1
- package/dist/cjs/agentic/improvement/RuleEngine.js +10 -4
- package/dist/cjs/agentic/improvement/SelfEvolution.js +22 -17
- package/dist/cjs/agentic/improvement/SelfTestRegistry.d.ts +5 -0
- package/dist/cjs/agentic/improvement/SelfTestRegistry.js +129 -109
- package/dist/cjs/agentic/improvement/SkillSynthesizer.d.ts +1 -0
- package/dist/cjs/agentic/improvement/SkillSynthesizer.js +22 -13
- package/dist/cjs/agentic/improvement/StrategicPlanner.d.ts +1 -0
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +26 -19
- package/dist/cjs/agentic/improvement/governance/AuditContext.d.ts +17 -0
- package/dist/cjs/agentic/improvement/governance/AuditContext.js +2 -0
- package/dist/cjs/agentic/improvement/governance/BudgetAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/BudgetAuditor.js +50 -0
- package/dist/cjs/agentic/improvement/governance/EmergenceAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/EmergenceAuditor.js +37 -0
- package/dist/cjs/agentic/improvement/governance/MaintenanceOracle.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/MaintenanceOracle.js +67 -0
- package/dist/cjs/agentic/improvement/governance/PerformanceAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/PerformanceAuditor.js +43 -0
- package/dist/cjs/agentic/improvement/governance/PersonaAuditor.d.ts +6 -0
- package/dist/cjs/agentic/improvement/governance/PersonaAuditor.js +74 -0
- package/dist/cjs/agentic/improvement/governance/RemediationEngine.d.ts +5 -0
- package/dist/cjs/agentic/improvement/governance/RemediationEngine.js +43 -0
- package/dist/cjs/agentic/improvement/governance/SkillAuditor.d.ts +5 -0
- package/dist/cjs/agentic/improvement/governance/SkillAuditor.js +52 -0
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.d.ts +5 -0
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.js +54 -12
- package/dist/cjs/agentic/telemetry/EventHarvester.d.ts +1 -1
- package/dist/cjs/agentic/telemetry/EventHarvester.js +10 -3
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.d.ts +7 -2
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.js +49 -8
- package/dist/cjs/agentic/telemetry/TelemetryOrchestrator.d.ts +4 -1
- package/dist/cjs/agentic/telemetry/TelemetryOrchestrator.js +38 -11
- package/dist/cjs/cli/commands/inspect.js +40 -1
- package/dist/cjs/cli/commands/watch.js +31 -25
- package/dist/cjs/cli/index.js +0 -0
- package/dist/cjs/dialect/sqlite/sqlite-introspector.js +15 -5
- package/dist/cjs/helpers/agent-schema.js +15 -14
- package/dist/cjs/migration/data_migrator.js +4 -4
- package/dist/cjs/migration/schema_differ.js +37 -15
- package/dist/cjs/types/index.d.ts +12 -0
- package/dist/cjs/util/safe-sql-helpers.js +7 -10
- package/dist/esm/agentic/ActionJournal.d.ts +5 -2
- package/dist/esm/agentic/ActionJournal.js +13 -5
- package/dist/esm/agentic/CapabilityManager.d.ts +7 -0
- package/dist/esm/agentic/CapabilityManager.js +84 -7
- package/dist/esm/agentic/CognitiveRepository.js +3 -6
- package/dist/esm/agentic/Cortex.d.ts +4 -0
- package/dist/esm/agentic/Cortex.js +38 -17
- package/dist/esm/agentic/EpisodicMemory.d.ts +5 -1
- package/dist/esm/agentic/EpisodicMemory.js +11 -4
- package/dist/esm/agentic/PersonaManager.js +37 -31
- package/dist/esm/agentic/PolicyEnforcer.d.ts +6 -1
- package/dist/esm/agentic/PolicyEnforcer.js +74 -17
- package/dist/esm/agentic/ResourceMonitor.d.ts +9 -0
- package/dist/esm/agentic/ResourceMonitor.js +36 -2
- package/dist/esm/agentic/SessionManager.js +24 -17
- package/dist/esm/agentic/VectorIndexer.d.ts +1 -0
- package/dist/esm/agentic/VectorIndexer.js +26 -17
- package/dist/esm/agentic/improvement/AblationEngine.d.ts +4 -6
- package/dist/esm/agentic/improvement/AblationEngine.js +57 -37
- package/dist/esm/agentic/improvement/ActionRefiner.js +30 -14
- package/dist/esm/agentic/improvement/ConflictResolver.d.ts +3 -1
- package/dist/esm/agentic/improvement/ConflictResolver.js +59 -47
- package/dist/esm/agentic/improvement/CortexJanitor.js +11 -0
- package/dist/esm/agentic/improvement/CuriosityEngine.d.ts +1 -1
- package/dist/esm/agentic/improvement/CuriosityEngine.js +48 -21
- package/dist/esm/agentic/improvement/EvolutionRitual.js +26 -14
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +16 -4
- package/dist/esm/agentic/improvement/GoalArchitect.d.ts +6 -2
- package/dist/esm/agentic/improvement/GoalArchitect.js +72 -34
- package/dist/esm/agentic/improvement/GovernanceManager.d.ts +20 -6
- package/dist/esm/agentic/improvement/GovernanceManager.js +134 -155
- package/dist/esm/agentic/improvement/HiveLink.d.ts +7 -3
- package/dist/esm/agentic/improvement/HiveLink.js +135 -113
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +43 -35
- package/dist/esm/agentic/improvement/QuotaManager.d.ts +41 -0
- package/dist/esm/agentic/improvement/QuotaManager.js +182 -0
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +50 -25
- package/dist/esm/agentic/improvement/ReflectionEngine.d.ts +4 -1
- package/dist/esm/agentic/improvement/ReflectionEngine.js +3 -1
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +27 -16
- package/dist/esm/agentic/improvement/RuleEngine.d.ts +1 -1
- package/dist/esm/agentic/improvement/RuleEngine.js +10 -4
- package/dist/esm/agentic/improvement/SelfEvolution.js +22 -17
- package/dist/esm/agentic/improvement/SelfTestRegistry.d.ts +5 -0
- package/dist/esm/agentic/improvement/SelfTestRegistry.js +129 -109
- package/dist/esm/agentic/improvement/SkillSynthesizer.d.ts +1 -0
- package/dist/esm/agentic/improvement/SkillSynthesizer.js +22 -13
- package/dist/esm/agentic/improvement/StrategicPlanner.d.ts +1 -0
- package/dist/esm/agentic/improvement/StrategicPlanner.js +26 -19
- package/dist/esm/agentic/improvement/governance/AuditContext.d.ts +17 -0
- package/dist/esm/agentic/improvement/governance/AuditContext.js +2 -0
- package/dist/esm/agentic/improvement/governance/BudgetAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/BudgetAuditor.js +47 -0
- package/dist/esm/agentic/improvement/governance/EmergenceAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/EmergenceAuditor.js +34 -0
- package/dist/esm/agentic/improvement/governance/MaintenanceOracle.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/MaintenanceOracle.js +64 -0
- package/dist/esm/agentic/improvement/governance/PerformanceAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/PerformanceAuditor.js +40 -0
- package/dist/esm/agentic/improvement/governance/PersonaAuditor.d.ts +6 -0
- package/dist/esm/agentic/improvement/governance/PersonaAuditor.js +71 -0
- package/dist/esm/agentic/improvement/governance/RemediationEngine.d.ts +5 -0
- package/dist/esm/agentic/improvement/governance/RemediationEngine.js +40 -0
- package/dist/esm/agentic/improvement/governance/SkillAuditor.d.ts +5 -0
- package/dist/esm/agentic/improvement/governance/SkillAuditor.js +49 -0
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.d.ts +5 -0
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.js +54 -12
- package/dist/esm/agentic/telemetry/EventHarvester.d.ts +1 -1
- package/dist/esm/agentic/telemetry/EventHarvester.js +10 -3
- package/dist/esm/agentic/telemetry/ResearchAlchemist.d.ts +7 -2
- package/dist/esm/agentic/telemetry/ResearchAlchemist.js +49 -8
- package/dist/esm/agentic/telemetry/TelemetryOrchestrator.d.ts +4 -1
- package/dist/esm/agentic/telemetry/TelemetryOrchestrator.js +38 -11
- package/dist/esm/cli/commands/inspect.js +40 -1
- package/dist/esm/cli/commands/watch.js +31 -25
- package/dist/esm/dialect/sqlite/sqlite-introspector.js +15 -5
- package/dist/esm/helpers/agent-schema.js +15 -14
- package/dist/esm/migration/data_migrator.js +4 -4
- package/dist/esm/migration/schema_differ.js +37 -15
- package/dist/esm/types/index.d.ts +12 -0
- package/dist/esm/util/safe-sql-helpers.js +7 -10
- package/package.json +44 -40
|
@@ -24,62 +24,69 @@ class HiveLink {
|
|
|
24
24
|
* Promote high-confidence local knowledge to global "Hive" knowledge.
|
|
25
25
|
* This creates a new, session-agnostic entry or updates an existing global one.
|
|
26
26
|
*/
|
|
27
|
-
async broadcastKnowledge(
|
|
28
|
-
|
|
27
|
+
async broadcastKnowledge(options = {}) {
|
|
28
|
+
const minConfidence = options.minConfidence ?? 0.9;
|
|
29
|
+
const limit = options.limit ?? 100;
|
|
30
|
+
const offset = options.offset ?? 0;
|
|
31
|
+
console.log(`[HiveLink] Broadcasting knowledge (limit=${limit}, offset=${offset}) with confidence >= ${minConfidence}`);
|
|
29
32
|
// Find high-confidence items that are "local" (have a source_session_id)
|
|
30
33
|
const items = (await this.typedDb
|
|
31
34
|
.selectFrom(this.knowledgeTable)
|
|
32
35
|
.selectAll()
|
|
33
36
|
.where('confidence', '>=', minConfidence)
|
|
34
37
|
.where('source_session_id', 'is not', null) // Only local items
|
|
38
|
+
.limit(limit)
|
|
39
|
+
.offset(offset)
|
|
35
40
|
.execute());
|
|
36
41
|
let promotedCount = 0;
|
|
37
42
|
for (const item of items) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
tags.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
43
|
+
await this.db.transaction().execute(async (trx) => {
|
|
44
|
+
// Check if a global version already exists
|
|
45
|
+
const existingGlobal = await trx
|
|
46
|
+
.selectFrom(this.knowledgeTable)
|
|
47
|
+
.selectAll()
|
|
48
|
+
.where('entity', '=', item.entity)
|
|
49
|
+
.where('fact', '=', item.fact)
|
|
50
|
+
.where('source_session_id', 'is', null)
|
|
51
|
+
.forUpdate() // Audit Phase 15: prevent concurrent promotion duplication
|
|
52
|
+
.executeTakeFirst();
|
|
53
|
+
if (existingGlobal) {
|
|
54
|
+
// Reinforce existing global knowledge
|
|
55
|
+
const newConfidence = Math.min(0.99, Math.max(existingGlobal.confidence, item.confidence) + 0.01);
|
|
56
|
+
await trx
|
|
57
|
+
.updateTable(this.knowledgeTable)
|
|
58
|
+
.set({
|
|
59
|
+
confidence: newConfidence,
|
|
60
|
+
updated_at: new Date(),
|
|
61
|
+
})
|
|
62
|
+
.where('id', '=', existingGlobal.id)
|
|
63
|
+
.execute();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Create new global knowledge
|
|
67
|
+
const tags = item.tags ? [...item.tags] : [];
|
|
68
|
+
if (!tags.includes('hive_mind'))
|
|
69
|
+
tags.push('hive_mind');
|
|
70
|
+
await trx
|
|
71
|
+
.insertInto(this.knowledgeTable)
|
|
72
|
+
.values({
|
|
73
|
+
entity: item.entity,
|
|
74
|
+
fact: item.fact,
|
|
75
|
+
confidence: item.confidence,
|
|
76
|
+
source_session_id: null,
|
|
77
|
+
tags: JSON.stringify(tags),
|
|
78
|
+
metadata: JSON.stringify({
|
|
79
|
+
...item.metadata,
|
|
80
|
+
promoted_from: item.id,
|
|
81
|
+
promoted_at: new Date(),
|
|
82
|
+
}),
|
|
83
|
+
created_at: new Date(),
|
|
84
|
+
updated_at: new Date(),
|
|
85
|
+
})
|
|
86
|
+
.execute();
|
|
87
|
+
promotedCount++;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
83
90
|
}
|
|
84
91
|
return promotedCount;
|
|
85
92
|
}
|
|
@@ -104,8 +111,8 @@ class HiveLink {
|
|
|
104
111
|
return Number(result[0]?.numUpdatedRows ?? 1);
|
|
105
112
|
}
|
|
106
113
|
/**
|
|
107
|
-
* Propagate high-performing capabilities globally
|
|
108
|
-
*
|
|
114
|
+
* Propagate high-performing capabilities globally using the "Sovereign Draft" protocol.
|
|
115
|
+
* Uses Bayesian Convergence and Shadow Promotion to avoid deadlocks.
|
|
109
116
|
*/
|
|
110
117
|
async broadcastSkills() {
|
|
111
118
|
if (!this.config.evolution?.enableHiveLink &&
|
|
@@ -113,81 +120,96 @@ class HiveLink {
|
|
|
113
120
|
console.log('[HiveLink] Skill broadcasting disabled by config.');
|
|
114
121
|
return 0;
|
|
115
122
|
}
|
|
116
|
-
console.log(`[HiveLink]
|
|
123
|
+
console.log(`[HiveLink] Executing Sovereign Draft for emergent skills...`);
|
|
117
124
|
let broadcastCount = 0;
|
|
118
125
|
const capTable = this.config.capabilitiesTable || 'agent_capabilities';
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
// 1. Resolve Verified Skills with Bayesian "Alpha" selection
|
|
127
|
+
const verifiedSkills = await this.cortex.capabilities.getCapabilities('verified');
|
|
128
|
+
// Group verified skills by lineage (base tool name)
|
|
129
|
+
const lineageGroups = new Map();
|
|
130
|
+
for (const skill of verifiedSkills) {
|
|
131
|
+
const meta = typeof skill.metadata === 'string' ? JSON.parse(skill.metadata) : (skill.metadata || {});
|
|
132
|
+
const lineage = meta.lineage || skill.name;
|
|
133
|
+
if (!lineageGroups.has(lineage))
|
|
134
|
+
lineageGroups.set(lineage, []);
|
|
135
|
+
lineageGroups.get(lineage).push({ skill, meta });
|
|
136
|
+
}
|
|
137
|
+
for (const [lineage, variants] of lineageGroups.entries()) {
|
|
138
|
+
// Bayesian Winner Selection
|
|
139
|
+
// Score = (anchored_reliability * totalCount + K * prior) / (totalCount + K)
|
|
140
|
+
// For simplicity, we use anchored_reliability which already incorporates this weighting
|
|
141
|
+
const alphaCandidate = variants.reduce((prev, curr) => {
|
|
142
|
+
const pAnchored = prev.meta.anchored_reliability ?? 0;
|
|
143
|
+
const cAnchored = curr.meta.anchored_reliability ?? 0;
|
|
144
|
+
return cAnchored > pAnchored ? curr : prev;
|
|
145
|
+
});
|
|
146
|
+
// Non-Blocking Set Update: Flag Alpha and Shadow versions
|
|
147
|
+
await this.db.transaction().execute(async (trx) => {
|
|
148
|
+
const currentMeta = alphaCandidate.meta || {};
|
|
149
|
+
const updatedMeta = {
|
|
150
|
+
...currentMeta,
|
|
151
|
+
is_alpha: true,
|
|
152
|
+
broadcasted: true,
|
|
153
|
+
broadcasted_at: new Date()
|
|
154
|
+
};
|
|
155
|
+
// Flag the winner as Alpha
|
|
156
|
+
// Audit Phase 15: Lock candidate before promotion
|
|
157
|
+
const winner = await trx
|
|
131
158
|
.selectFrom(capTable)
|
|
132
|
-
.
|
|
133
|
-
.where('
|
|
134
|
-
.
|
|
135
|
-
.where('id', '!=', skill.id)
|
|
159
|
+
.select('id')
|
|
160
|
+
.where('id', '=', alphaCandidate.skill.id)
|
|
161
|
+
.forUpdate()
|
|
136
162
|
.executeTakeFirst();
|
|
137
|
-
|
|
138
|
-
if (competitor) {
|
|
139
|
-
const comp = competitor;
|
|
140
|
-
const compRel = comp.reliability || 0;
|
|
141
|
-
// Performance-Based Conflict Resolution: Only broadcast if reliability is strictly better
|
|
142
|
-
// or if it's a direct version upgrade with equal/better reliability
|
|
143
|
-
const isNewer = this.compareVersions(skill.version, comp.version) > 0;
|
|
144
|
-
if (compRel > skill.reliability) {
|
|
145
|
-
shouldBroadcast = false;
|
|
146
|
-
}
|
|
147
|
-
else if (compRel === skill.reliability && !isNewer) {
|
|
148
|
-
shouldBroadcast = false;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (shouldBroadcast) {
|
|
163
|
+
if (winner) {
|
|
152
164
|
await trx
|
|
153
165
|
.updateTable(capTable)
|
|
154
166
|
.set({
|
|
155
|
-
metadata: JSON.stringify(
|
|
156
|
-
...meta,
|
|
157
|
-
broadcasted: true,
|
|
158
|
-
hive_verified: true,
|
|
159
|
-
broadcasted_at: new Date(),
|
|
160
|
-
conflict_resolved: !!competitor,
|
|
161
|
-
}),
|
|
167
|
+
metadata: JSON.stringify(updatedMeta),
|
|
162
168
|
})
|
|
163
|
-
.where('id', '=',
|
|
169
|
+
.where('id', '=', winner.id)
|
|
164
170
|
.execute();
|
|
165
|
-
broadcastCount++;
|
|
166
171
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
.
|
|
178
|
-
|
|
179
|
-
...
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
.where('id', '=', skill.id)
|
|
186
|
-
.execute();
|
|
187
|
-
broadcastCount++;
|
|
172
|
+
// Flag others in the same lineage as Shadow (Dialect-safe approach)
|
|
173
|
+
const shadowIds = variants
|
|
174
|
+
.filter(v => v.skill.id !== alphaCandidate.skill.id)
|
|
175
|
+
.map(v => v.skill.id);
|
|
176
|
+
if (shadowIds.length > 0) {
|
|
177
|
+
// We fetch and update individually or use a bulk update if the dialect supports complex JSON manipulation.
|
|
178
|
+
// For maximum compatibility (Postgres/SQLite), we do it in a loop for the shadows if the count is small.
|
|
179
|
+
for (const sid of shadowIds) {
|
|
180
|
+
const sMatch = variants.find(v => v.skill.id === sid);
|
|
181
|
+
const sMeta = sMatch?.meta || {};
|
|
182
|
+
await trx.updateTable(capTable)
|
|
183
|
+
.set({
|
|
184
|
+
metadata: JSON.stringify({ ...sMeta, is_alpha: false, is_shadow: true }),
|
|
185
|
+
status: 'experimental'
|
|
186
|
+
})
|
|
187
|
+
.where('id', '=', sid)
|
|
188
|
+
.execute();
|
|
189
|
+
}
|
|
188
190
|
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
+
});
|
|
192
|
+
broadcastCount += variants.length;
|
|
193
|
+
}
|
|
194
|
+
// 2. Broadcast Blacklisted Skills (Immune Prophet)
|
|
195
|
+
const blacklisted = await this.cortex.capabilities.getCapabilities('blacklisted');
|
|
196
|
+
const blackIDs = blacklisted
|
|
197
|
+
.filter(s => {
|
|
198
|
+
const meta = typeof s.metadata === 'string' ? JSON.parse(s.metadata) : (s.metadata || {});
|
|
199
|
+
return !meta.broadcasted;
|
|
200
|
+
})
|
|
201
|
+
.map(s => s.id);
|
|
202
|
+
if (blackIDs.length > 0) {
|
|
203
|
+
await this.db
|
|
204
|
+
.updateTable(capTable)
|
|
205
|
+
.set({
|
|
206
|
+
metadata: (0, sql_js_1.sql) `json_set(metadata, '$.broadcasted', true, '$.hive_blacklisted', true)`,
|
|
207
|
+
updated_at: new Date()
|
|
208
|
+
})
|
|
209
|
+
.where('id', 'in', blackIDs)
|
|
210
|
+
.execute();
|
|
211
|
+
broadcastCount += blackIDs.length;
|
|
212
|
+
}
|
|
191
213
|
return broadcastCount;
|
|
192
214
|
}
|
|
193
215
|
/**
|
|
@@ -103,6 +103,7 @@ class KnowledgeDistiller {
|
|
|
103
103
|
return this.parseKnowledge(updated);
|
|
104
104
|
}
|
|
105
105
|
// Conflict Detection: Check if a similar entity has a conflicting fact
|
|
106
|
+
// Audit Phase 11: Explicit transaction propagation
|
|
106
107
|
await this.challengeKnowledge(entity, fact, confidence, trx);
|
|
107
108
|
// Create new
|
|
108
109
|
const initialMeta = {
|
|
@@ -197,35 +198,38 @@ class KnowledgeDistiller {
|
|
|
197
198
|
* Record a retrieval hit for a knowledge item.
|
|
198
199
|
*/
|
|
199
200
|
async recordHit(id) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
201
|
+
await this.db.transaction().execute(async (trx) => {
|
|
202
|
+
const existing = await trx
|
|
203
|
+
.selectFrom(this.knowledgeTable)
|
|
204
|
+
.selectAll()
|
|
205
|
+
.where('id', '=', id)
|
|
206
|
+
.forUpdate() // Audit Phase 11: Atomic hit record
|
|
207
|
+
.executeTakeFirst();
|
|
208
|
+
if (!existing)
|
|
209
|
+
return;
|
|
210
|
+
const metadata = typeof existing.metadata === 'string'
|
|
211
|
+
? JSON.parse(existing.metadata)
|
|
212
|
+
: existing.metadata || {};
|
|
213
|
+
metadata.hit_count = (metadata.hit_count || 0) + 1;
|
|
214
|
+
metadata.last_retrieved_at = new Date().toISOString();
|
|
215
|
+
await trx
|
|
216
|
+
.updateTable(this.knowledgeTable)
|
|
217
|
+
.set({
|
|
218
|
+
metadata: JSON.stringify(metadata),
|
|
219
|
+
updated_at: new Date(),
|
|
220
|
+
})
|
|
221
|
+
.where('id', '=', id)
|
|
222
|
+
.execute();
|
|
223
|
+
// Production Hardening: Emit a metric event for this hit to enable efficient hotspot detection
|
|
224
|
+
await trx
|
|
225
|
+
.insertInto(this.config.metricsTable || 'agent_metrics')
|
|
226
|
+
.values({
|
|
227
|
+
metric_name: `entity_hit_${existing.entity}`,
|
|
228
|
+
metric_value: 1,
|
|
229
|
+
created_at: new Date(),
|
|
230
|
+
})
|
|
231
|
+
.execute();
|
|
232
|
+
});
|
|
229
233
|
}
|
|
230
234
|
/**
|
|
231
235
|
* Calculate the "Fitness" of a memory item.
|
|
@@ -248,6 +252,8 @@ class KnowledgeDistiller {
|
|
|
248
252
|
* we degrade the confidence of the old facts.
|
|
249
253
|
*/
|
|
250
254
|
async challengeKnowledge(entity, competingFact, confidence, trxOrDb = this.db) {
|
|
255
|
+
// Audit Phase 11: Semantic sanitization of competing fact
|
|
256
|
+
const safeFact = competingFact.slice(0, 500).replace(/[\u0000-\u001F\u007F-\u009F]/g, '').replace(/<\|.*?\|>/g, '');
|
|
251
257
|
const query = trxOrDb
|
|
252
258
|
.selectFrom(this.knowledgeTable)
|
|
253
259
|
.selectAll()
|
|
@@ -269,7 +275,7 @@ class KnowledgeDistiller {
|
|
|
269
275
|
newStatus = 'disputed';
|
|
270
276
|
newMeta = {
|
|
271
277
|
...newMeta,
|
|
272
|
-
status_reason: `Contradicted by: ${
|
|
278
|
+
status_reason: `Contradicted by: ${safeFact}`,
|
|
273
279
|
};
|
|
274
280
|
penalty = 0.1;
|
|
275
281
|
}
|
|
@@ -277,7 +283,7 @@ class KnowledgeDistiller {
|
|
|
277
283
|
newStatus = 'deprecated';
|
|
278
284
|
newMeta = {
|
|
279
285
|
...newMeta,
|
|
280
|
-
status_reason: `Superseded by: ${
|
|
286
|
+
status_reason: `Superseded by: ${safeFact}`,
|
|
281
287
|
};
|
|
282
288
|
penalty = 0.4;
|
|
283
289
|
}
|
|
@@ -418,22 +424,24 @@ class KnowledgeDistiller {
|
|
|
418
424
|
*/
|
|
419
425
|
async consolidateKnowledge() {
|
|
420
426
|
let totalMerged = 0;
|
|
421
|
-
// Find entities with multiple facts
|
|
427
|
+
// Find entities with multiple facts (Paginated to handle scale)
|
|
422
428
|
const candidates = await this.db
|
|
423
429
|
.selectFrom(this.knowledgeTable)
|
|
424
430
|
.select('entity')
|
|
425
431
|
.groupBy('entity')
|
|
426
432
|
.having((eb) => eb.fn.count('id'), '>', 1)
|
|
433
|
+
.limit(500) // Audit Phase 11: Chunked search
|
|
427
434
|
.execute();
|
|
428
435
|
for (const cand of candidates) {
|
|
429
436
|
const entity = cand.entity;
|
|
430
437
|
const items = await this.getKnowledgeByEntity(entity);
|
|
431
|
-
// Iterative merging inside the entity bucket
|
|
438
|
+
// Iterative merging inside the entity bucket (Paginated check)
|
|
432
439
|
const mergedIds = new Set();
|
|
433
|
-
|
|
440
|
+
const iterLimit = Math.min(items.length, 100);
|
|
441
|
+
for (let i = 0; i < iterLimit; i++) {
|
|
434
442
|
if (mergedIds.has(items[i].id))
|
|
435
443
|
continue;
|
|
436
|
-
for (let j = i + 1; j <
|
|
444
|
+
for (let j = i + 1; j < iterLimit; j++) {
|
|
437
445
|
if (mergedIds.has(items[j].id))
|
|
438
446
|
continue;
|
|
439
447
|
const sim = (0, similarity_js_1.calculateSimilarity)(items[i].fact, items[j].fact);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Kysely } from '../../kysely.js';
|
|
2
|
+
import type { AgenticConfig } from '../../types/index.js';
|
|
3
|
+
import type { Cortex } from '../Cortex.js';
|
|
4
|
+
/**
|
|
5
|
+
* QuotaManager enforces resource limits across personas and swarms.
|
|
6
|
+
*/
|
|
7
|
+
export declare class QuotaManager {
|
|
8
|
+
private db;
|
|
9
|
+
private cortex;
|
|
10
|
+
private config;
|
|
11
|
+
private resourcesTable;
|
|
12
|
+
private metricsTable;
|
|
13
|
+
private rateCache;
|
|
14
|
+
private readonly CACHE_TTL;
|
|
15
|
+
constructor(db: Kysely<any>, cortex: Cortex, config?: AgenticConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Check if a quota is violated for a given target.
|
|
18
|
+
*/
|
|
19
|
+
checkQuota(targetType: 'persona' | 'swarm' | 'global', targetId?: string | null): Promise<{
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
reason?: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Fetches active quotas for a given target.
|
|
25
|
+
*/
|
|
26
|
+
private getActiveQuotas;
|
|
27
|
+
/**
|
|
28
|
+
* Calculates current usage for a specific quota window.
|
|
29
|
+
*/
|
|
30
|
+
private getCurrentUsage;
|
|
31
|
+
/**
|
|
32
|
+
* Resolves exchange rate via persistent metric store or live update.
|
|
33
|
+
* Implements a true Oracle pattern for resource normalization.
|
|
34
|
+
*/
|
|
35
|
+
private getExchangeRate;
|
|
36
|
+
/**
|
|
37
|
+
* Manually sync exchange rates from an external provider (Oracle pulse).
|
|
38
|
+
*/
|
|
39
|
+
syncExchangeRates(rates: Record<string, number>): Promise<void>;
|
|
40
|
+
private getPeriodInMs;
|
|
41
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuotaManager = void 0;
|
|
4
|
+
const sql_js_1 = require("../../raw-builder/sql.js");
|
|
5
|
+
/**
|
|
6
|
+
* QuotaManager enforces resource limits across personas and swarms.
|
|
7
|
+
*/
|
|
8
|
+
class QuotaManager {
|
|
9
|
+
db;
|
|
10
|
+
cortex;
|
|
11
|
+
config;
|
|
12
|
+
resourcesTable;
|
|
13
|
+
metricsTable;
|
|
14
|
+
rateCache = new Map();
|
|
15
|
+
CACHE_TTL = 1000 * 60 * 60; // 1 hour cache
|
|
16
|
+
constructor(db, cortex, config = {}) {
|
|
17
|
+
this.db = db;
|
|
18
|
+
this.cortex = cortex;
|
|
19
|
+
this.config = config;
|
|
20
|
+
this.resourcesTable = config.resourcesTable || 'agent_resource_usage';
|
|
21
|
+
this.metricsTable = config.metricsTable || 'agent_metrics';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if a quota is violated for a given target.
|
|
25
|
+
*/
|
|
26
|
+
async checkQuota(targetType, targetId = null) {
|
|
27
|
+
const quotas = await this.getActiveQuotas(targetType, targetId);
|
|
28
|
+
for (const quota of quotas) {
|
|
29
|
+
const usage = await this.getCurrentUsage(quota);
|
|
30
|
+
// Currency Conversion Logic: Convert usage to target currency if specified
|
|
31
|
+
let normalizedUsage = usage;
|
|
32
|
+
if (quota.metric === 'cost' && quota.metadata?.currency && quota.metadata.currency !== 'USD') {
|
|
33
|
+
const rate = await this.getExchangeRate(quota.metadata.currency);
|
|
34
|
+
normalizedUsage = usage * rate;
|
|
35
|
+
}
|
|
36
|
+
if (normalizedUsage >= quota.limit) {
|
|
37
|
+
const limitStr = quota.metric === 'cost'
|
|
38
|
+
? `${quota.metadata?.currency || '$'}${quota.limit}`
|
|
39
|
+
: `${quota.limit}`;
|
|
40
|
+
return {
|
|
41
|
+
allowed: false,
|
|
42
|
+
reason: `Quota exceeded: ${quota.metric} limit is ${limitStr}, current is ${normalizedUsage.toFixed(4)} (${quota.period})`
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { allowed: true };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fetches active quotas for a given target.
|
|
50
|
+
*/
|
|
51
|
+
async getActiveQuotas(targetType, targetId) {
|
|
52
|
+
const quotas = [];
|
|
53
|
+
// 1. Fetch from PolicyEnforcer (Global & Type-specific)
|
|
54
|
+
const policies = await this.cortex.policies.getActivePolicies();
|
|
55
|
+
for (const policy of policies) {
|
|
56
|
+
if (policy.type === 'budget' &&
|
|
57
|
+
(policy.definition.targetType === targetType ||
|
|
58
|
+
(!policy.definition.targetType && targetType === 'global'))) {
|
|
59
|
+
quotas.push({
|
|
60
|
+
id: policy.id,
|
|
61
|
+
targetType: targetType,
|
|
62
|
+
targetId: targetId,
|
|
63
|
+
metric: policy.definition.metric || 'cost',
|
|
64
|
+
limit: policy.definition.limit ?? policy.definition.threshold ?? 0,
|
|
65
|
+
period: policy.definition.period || 'hourly',
|
|
66
|
+
currentUsage: 0,
|
|
67
|
+
createdAt: policy.createdAt,
|
|
68
|
+
updatedAt: policy.updatedAt,
|
|
69
|
+
metadata: policy.metadata
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// 2. Fetch from Persona metadata (Specific override)
|
|
74
|
+
if (targetType === 'persona' && targetId) {
|
|
75
|
+
const persona = await this.db
|
|
76
|
+
.selectFrom(this.config.personasTable || 'agent_personas')
|
|
77
|
+
.select('metadata')
|
|
78
|
+
.where('id', '=', targetId)
|
|
79
|
+
.executeTakeFirst();
|
|
80
|
+
if (persona) {
|
|
81
|
+
const meta = typeof persona.metadata === 'string'
|
|
82
|
+
? JSON.parse(persona.metadata)
|
|
83
|
+
: persona.metadata || {};
|
|
84
|
+
if (meta.quotas) {
|
|
85
|
+
quotas.push(...meta.quotas);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return quotas;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Calculates current usage for a specific quota window.
|
|
93
|
+
*/
|
|
94
|
+
async getCurrentUsage(quota) {
|
|
95
|
+
const windowMs = this.getPeriodInMs(quota.period);
|
|
96
|
+
const startTime = new Date(Date.now() - windowMs);
|
|
97
|
+
let query = this.db
|
|
98
|
+
.selectFrom(this.resourcesTable)
|
|
99
|
+
.where('created_at', '>', startTime);
|
|
100
|
+
if (quota.targetType === 'persona' && quota.targetId) {
|
|
101
|
+
query = query.where('agent_id', '=', quota.targetId);
|
|
102
|
+
}
|
|
103
|
+
else if (quota.targetType === 'swarm' && quota.targetId) {
|
|
104
|
+
// PRODUCTION HARDENING: Efficient JSON filtering
|
|
105
|
+
query = query.where((eb) => eb.or([
|
|
106
|
+
eb((0, sql_js_1.sql) `json_extract(metadata, '$.swarm_id')`, '=', quota.targetId),
|
|
107
|
+
eb((0, sql_js_1.sql) `metadata->>'swarm_id'`, '=', String(quota.targetId))
|
|
108
|
+
]));
|
|
109
|
+
}
|
|
110
|
+
const metricField = quota.metric === 'cost' ? 'cost' :
|
|
111
|
+
quota.metric === 'tokens_input' ? 'input_tokens' :
|
|
112
|
+
quota.metric === 'tokens_output' ? 'output_tokens' :
|
|
113
|
+
(0, sql_js_1.sql) `input_tokens + output_tokens`;
|
|
114
|
+
const result = await query
|
|
115
|
+
.select((eb) => eb.fn.sum(metricField).as('total'))
|
|
116
|
+
.executeTakeFirst();
|
|
117
|
+
const usage = Number(result?.total || 0);
|
|
118
|
+
// Audit Phase 7: Floating-point drift protection
|
|
119
|
+
const epsilon = 1e-10;
|
|
120
|
+
return usage < epsilon ? 0 : usage;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Resolves exchange rate via persistent metric store or live update.
|
|
124
|
+
* Implements a true Oracle pattern for resource normalization.
|
|
125
|
+
*/
|
|
126
|
+
async getExchangeRate(currency) {
|
|
127
|
+
// 1. Check in-memory cache
|
|
128
|
+
const cached = this.rateCache.get(currency);
|
|
129
|
+
if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
|
|
130
|
+
return cached.rate;
|
|
131
|
+
}
|
|
132
|
+
// 2. Check persistent metric store
|
|
133
|
+
const record = await this.db
|
|
134
|
+
.selectFrom(this.metricsTable)
|
|
135
|
+
.select(['metric_value', 'created_at'])
|
|
136
|
+
.where('metric_name', '=', `exchange_rate_${currency}`)
|
|
137
|
+
.orderBy('created_at', 'desc')
|
|
138
|
+
.executeTakeFirst();
|
|
139
|
+
if (record && Date.now() - new Date(record.created_at).getTime() < this.CACHE_TTL * 24) {
|
|
140
|
+
const rate = Number(record.metric_value);
|
|
141
|
+
this.rateCache.set(currency, { rate, timestamp: Date.now() });
|
|
142
|
+
return rate;
|
|
143
|
+
}
|
|
144
|
+
// 3. Fallback to base rates if unreachable (Statically hardened)
|
|
145
|
+
const baseRates = {
|
|
146
|
+
'ETH': 0.00032,
|
|
147
|
+
'BTC': 0.000015,
|
|
148
|
+
'EUR': 0.92,
|
|
149
|
+
'GBP': 0.79
|
|
150
|
+
};
|
|
151
|
+
const fallback = baseRates[currency] || 1.0;
|
|
152
|
+
// Log the need for sync
|
|
153
|
+
console.warn(`[QuotaManager] Exchange rate for ${currency} is stale or missing. Using hardened fallback: ${fallback}`);
|
|
154
|
+
return fallback;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Manually sync exchange rates from an external provider (Oracle pulse).
|
|
158
|
+
*/
|
|
159
|
+
async syncExchangeRates(rates) {
|
|
160
|
+
await this.db.transaction().execute(async (trx) => {
|
|
161
|
+
for (const [currency, rate] of Object.entries(rates)) {
|
|
162
|
+
await trx
|
|
163
|
+
.insertInto(this.metricsTable)
|
|
164
|
+
.values({
|
|
165
|
+
metric_name: `exchange_rate_${currency}`,
|
|
166
|
+
metric_value: rate,
|
|
167
|
+
created_at: new Date()
|
|
168
|
+
})
|
|
169
|
+
.execute();
|
|
170
|
+
this.rateCache.set(currency, { rate, timestamp: Date.now() });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
console.log(`[QuotaManager] Synchronized ${Object.keys(rates).length} exchange rates.`);
|
|
174
|
+
}
|
|
175
|
+
getPeriodInMs(period) {
|
|
176
|
+
switch (period) {
|
|
177
|
+
case 'hourly': return 3600000;
|
|
178
|
+
case 'daily': return 86400000;
|
|
179
|
+
case 'monthly': return 86400000 * 30;
|
|
180
|
+
case 'infinite': return Date.now();
|
|
181
|
+
default: return 3600000;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.QuotaManager = QuotaManager;
|