@timmeck/brain-core 2.0.4 → 2.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/dist/api/middleware.d.ts +62 -0
- package/dist/api/middleware.js +107 -0
- package/dist/api/middleware.js.map +1 -0
- package/dist/api/server.d.ts +7 -0
- package/dist/api/server.js +52 -14
- package/dist/api/server.js.map +1 -1
- package/dist/cross-brain/correlator.d.ts +92 -0
- package/dist/cross-brain/correlator.js +248 -0
- package/dist/cross-brain/correlator.js.map +1 -0
- package/dist/dashboard/hub-server.d.ts +9 -0
- package/dist/dashboard/hub-server.js +42 -0
- package/dist/dashboard/hub-server.js.map +1 -0
- package/dist/ecosystem/service.d.ts +64 -0
- package/dist/ecosystem/service.js +106 -0
- package/dist/ecosystem/service.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/ipc/errors.d.ts +32 -0
- package/dist/ipc/errors.js +50 -0
- package/dist/ipc/errors.js.map +1 -0
- package/dist/ipc/validation.d.ts +15 -0
- package/dist/ipc/validation.js +62 -0
- package/dist/ipc/validation.js.map +1 -0
- package/hub-dashboard.html +859 -0
- package/package.json +7 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { getLogger } from '../utils/logger.js';
|
|
2
|
+
const DEFAULT_MAX_EVENTS = 1000;
|
|
3
|
+
const DEFAULT_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
|
|
4
|
+
const DEFAULT_DECAY_FACTOR = 0.95;
|
|
5
|
+
const ACTIVE_BRAIN_THRESHOLD_MS = 60 * 1000; // 60 seconds
|
|
6
|
+
const FIVE_MINUTES_MS = 5 * 60 * 1000;
|
|
7
|
+
/**
|
|
8
|
+
* CrossBrainCorrelator — detects temporal correlations between events
|
|
9
|
+
* from different brains in the ecosystem.
|
|
10
|
+
*/
|
|
11
|
+
export class CrossBrainCorrelator {
|
|
12
|
+
logger = getLogger();
|
|
13
|
+
events = [];
|
|
14
|
+
correlations = new Map();
|
|
15
|
+
brainLastSeen = new Map();
|
|
16
|
+
maxEvents;
|
|
17
|
+
windowMs;
|
|
18
|
+
decayFactor;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.maxEvents = config?.maxEvents ?? DEFAULT_MAX_EVENTS;
|
|
21
|
+
this.windowMs = config?.windowMs ?? DEFAULT_WINDOW_MS;
|
|
22
|
+
this.decayFactor = config?.decayFactor ?? DEFAULT_DECAY_FACTOR;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Record an event from a brain. Adds to the circular buffer and
|
|
26
|
+
* runs correlation detection against recent events from OTHER brains.
|
|
27
|
+
*/
|
|
28
|
+
recordEvent(source, event, data) {
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
const correlatorEvent = {
|
|
31
|
+
source,
|
|
32
|
+
event,
|
|
33
|
+
data,
|
|
34
|
+
timestamp: now,
|
|
35
|
+
};
|
|
36
|
+
// Circular buffer: splice oldest when over capacity
|
|
37
|
+
if (this.events.length >= this.maxEvents) {
|
|
38
|
+
this.events.splice(0, this.events.length - this.maxEvents + 1);
|
|
39
|
+
}
|
|
40
|
+
this.events.push(correlatorEvent);
|
|
41
|
+
this.brainLastSeen.set(source, now);
|
|
42
|
+
this.logger.debug(`Correlator recorded event: ${source}/${event}`);
|
|
43
|
+
this.detectCorrelations();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Look at the last event added. Find events from other brains within
|
|
47
|
+
* the correlation window. For each match, create or update a Correlation.
|
|
48
|
+
*/
|
|
49
|
+
detectCorrelations() {
|
|
50
|
+
if (this.events.length < 2)
|
|
51
|
+
return;
|
|
52
|
+
const latest = this.events[this.events.length - 1];
|
|
53
|
+
const windowStart = latest.timestamp - this.windowMs;
|
|
54
|
+
for (let i = this.events.length - 2; i >= 0; i--) {
|
|
55
|
+
const other = this.events[i];
|
|
56
|
+
// Stop scanning once we're outside the window
|
|
57
|
+
if (other.timestamp < windowStart)
|
|
58
|
+
break;
|
|
59
|
+
// Only correlate events from different brains
|
|
60
|
+
if (other.source === latest.source)
|
|
61
|
+
continue;
|
|
62
|
+
const type = this.classifyCorrelation(latest, other);
|
|
63
|
+
const id = this.buildCorrelationId(latest, other);
|
|
64
|
+
const existing = this.correlations.get(id);
|
|
65
|
+
if (existing) {
|
|
66
|
+
existing.count += 1;
|
|
67
|
+
existing.strength = Math.min(1, existing.count / 10);
|
|
68
|
+
existing.lastSeen = latest.timestamp;
|
|
69
|
+
existing.type = type; // update type in case data changed
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Determine stable ordering (alphabetical by descriptor)
|
|
73
|
+
const descA = `${latest.source}:${latest.event}`;
|
|
74
|
+
const descB = `${other.source}:${other.event}`;
|
|
75
|
+
const [first, second] = [descA, descB].sort();
|
|
76
|
+
const isSwapped = first !== descA;
|
|
77
|
+
const correlation = {
|
|
78
|
+
id,
|
|
79
|
+
sourceA: isSwapped ? other.source : latest.source,
|
|
80
|
+
eventA: isSwapped ? other.event : latest.event,
|
|
81
|
+
sourceB: isSwapped ? latest.source : other.source,
|
|
82
|
+
eventB: isSwapped ? latest.event : other.event,
|
|
83
|
+
type,
|
|
84
|
+
strength: Math.min(1, 1 / 10), // first occurrence
|
|
85
|
+
count: 1,
|
|
86
|
+
lastSeen: latest.timestamp,
|
|
87
|
+
};
|
|
88
|
+
this.correlations.set(id, correlation);
|
|
89
|
+
this.logger.debug(`New correlation detected: ${id} (type: ${type})`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Classify the correlation type based on the two events.
|
|
95
|
+
* Order-independent: checks both directions.
|
|
96
|
+
*/
|
|
97
|
+
classifyCorrelation(a, b) {
|
|
98
|
+
// Check both orderings for error + trade correlation
|
|
99
|
+
const errorEvent = [a, b].find((e) => e.event === 'error:reported');
|
|
100
|
+
const tradeEvent = [a, b].find((e) => e.event === 'trade:outcome');
|
|
101
|
+
if (errorEvent && tradeEvent) {
|
|
102
|
+
const tradeData = tradeEvent.data;
|
|
103
|
+
if (tradeData && tradeData.win === false) {
|
|
104
|
+
return 'error-trade-loss';
|
|
105
|
+
}
|
|
106
|
+
if (tradeData && tradeData.win === true) {
|
|
107
|
+
return 'error-trade-win';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Error + publish correlation (order-independent)
|
|
111
|
+
const hasError = [a, b].some((e) => e.event === 'error:reported');
|
|
112
|
+
const hasPublish = [a, b].some((e) => e.event === 'post:published');
|
|
113
|
+
if (hasError && hasPublish) {
|
|
114
|
+
return 'publish-during-errors';
|
|
115
|
+
}
|
|
116
|
+
// Insight from one brain + anything from another
|
|
117
|
+
const hasInsight = [a, b].some((e) => e.event === 'insight:created');
|
|
118
|
+
if (hasInsight) {
|
|
119
|
+
return 'cross-brain-insight';
|
|
120
|
+
}
|
|
121
|
+
return 'temporal-co-occurrence';
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build a stable correlation ID by sorting the two event descriptors
|
|
125
|
+
* alphabetically. This ensures the same pair always produces the same ID
|
|
126
|
+
* regardless of arrival order.
|
|
127
|
+
*/
|
|
128
|
+
buildCorrelationId(a, b) {
|
|
129
|
+
const descA = `${a.source}:${a.event}`;
|
|
130
|
+
const descB = `${b.source}:${b.event}`;
|
|
131
|
+
const sorted = [descA, descB].sort();
|
|
132
|
+
return `${sorted[0]}\u2194${sorted[1]}`; // ↔ character
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Return correlations sorted by strength (descending).
|
|
136
|
+
* Optionally filter by minimum strength.
|
|
137
|
+
*/
|
|
138
|
+
getCorrelations(minStrength) {
|
|
139
|
+
const all = Array.from(this.correlations.values());
|
|
140
|
+
const filtered = minStrength !== undefined
|
|
141
|
+
? all.filter((c) => c.strength >= minStrength)
|
|
142
|
+
: all;
|
|
143
|
+
return filtered.sort((a, b) => b.strength - a.strength);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Return the most recent events from the buffer.
|
|
147
|
+
*/
|
|
148
|
+
getTimeline(limit = 50) {
|
|
149
|
+
return this.events.slice(-limit);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Compute ecosystem health based on recent events and correlations.
|
|
153
|
+
*/
|
|
154
|
+
getHealth() {
|
|
155
|
+
const now = Date.now();
|
|
156
|
+
const fiveMinAgo = now - FIVE_MINUTES_MS;
|
|
157
|
+
// Count recent errors
|
|
158
|
+
const recentErrors = this.events.filter((e) => e.event === 'error:reported' && e.timestamp >= fiveMinAgo).length;
|
|
159
|
+
// Count recent trade losses
|
|
160
|
+
const recentTradeLosses = this.events.filter((e) => {
|
|
161
|
+
if (e.event !== 'trade:outcome' || e.timestamp < fiveMinAgo)
|
|
162
|
+
return false;
|
|
163
|
+
const d = e.data;
|
|
164
|
+
return d && d.win === false;
|
|
165
|
+
}).length;
|
|
166
|
+
// Count error-trade-loss correlations seen in last 5 min
|
|
167
|
+
const recentLossCorrelations = Array.from(this.correlations.values()).filter((c) => c.type === 'error-trade-loss' && c.lastSeen >= fiveMinAgo).length;
|
|
168
|
+
// Active brains
|
|
169
|
+
const activeBrains = this.getActiveBrains();
|
|
170
|
+
// Calculate score
|
|
171
|
+
let score = 100;
|
|
172
|
+
score -= recentErrors * 10;
|
|
173
|
+
score -= recentLossCorrelations * 15;
|
|
174
|
+
score += activeBrains.length * 5;
|
|
175
|
+
// Clamp to 0-100
|
|
176
|
+
score = Math.max(0, Math.min(100, score));
|
|
177
|
+
// Determine status
|
|
178
|
+
let status;
|
|
179
|
+
if (score >= 70) {
|
|
180
|
+
status = 'healthy';
|
|
181
|
+
}
|
|
182
|
+
else if (score >= 40) {
|
|
183
|
+
status = 'degraded';
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
status = 'critical';
|
|
187
|
+
}
|
|
188
|
+
// Generate alerts
|
|
189
|
+
const alerts = [];
|
|
190
|
+
if (recentErrors > 0) {
|
|
191
|
+
alerts.push(`${recentErrors} error(s) reported in the last 5 minutes`);
|
|
192
|
+
}
|
|
193
|
+
if (recentLossCorrelations > 0) {
|
|
194
|
+
alerts.push(`${recentLossCorrelations} error-trade-loss correlation(s) detected recently`);
|
|
195
|
+
}
|
|
196
|
+
// Alert on strong concerning correlations
|
|
197
|
+
for (const c of this.correlations.values()) {
|
|
198
|
+
if (c.strength >= 0.5 &&
|
|
199
|
+
c.lastSeen >= fiveMinAgo &&
|
|
200
|
+
(c.type === 'error-trade-loss' || c.type === 'publish-during-errors')) {
|
|
201
|
+
alerts.push(`Strong ${c.type} correlation between ${c.sourceA} and ${c.sourceB} (strength: ${c.strength.toFixed(2)}, seen ${c.count} times)`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (activeBrains.length === 0) {
|
|
205
|
+
alerts.push('No active brains detected in the last 60 seconds');
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
score,
|
|
209
|
+
status,
|
|
210
|
+
activeBrains: activeBrains.length,
|
|
211
|
+
totalEvents: this.events.length,
|
|
212
|
+
correlations: this.correlations.size,
|
|
213
|
+
recentErrors,
|
|
214
|
+
recentTradeLosses,
|
|
215
|
+
alerts,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Return brain names that have sent an event in the last 60 seconds.
|
|
220
|
+
*/
|
|
221
|
+
getActiveBrains() {
|
|
222
|
+
const now = Date.now();
|
|
223
|
+
const threshold = now - ACTIVE_BRAIN_THRESHOLD_MS;
|
|
224
|
+
const active = [];
|
|
225
|
+
for (const [brain, lastSeen] of this.brainLastSeen) {
|
|
226
|
+
if (lastSeen >= threshold) {
|
|
227
|
+
active.push(brain);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return active;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Return the total number of events currently in the buffer.
|
|
234
|
+
*/
|
|
235
|
+
getEventCount() {
|
|
236
|
+
return this.events.length;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Reset all state: events, correlations, and brain tracking.
|
|
240
|
+
*/
|
|
241
|
+
clear() {
|
|
242
|
+
this.events = [];
|
|
243
|
+
this.correlations.clear();
|
|
244
|
+
this.brainLastSeen.clear();
|
|
245
|
+
this.logger.debug('Correlator state cleared');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=correlator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlator.js","sourceRoot":"","sources":["../../src/cross-brain/correlator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DashboardServer } from './server.js';
|
|
2
|
+
import type { EcosystemService } from '../ecosystem/service.js';
|
|
3
|
+
import type { CrossBrainCorrelator } from '../cross-brain/correlator.js';
|
|
4
|
+
export interface HubDashboardOptions {
|
|
5
|
+
port: number;
|
|
6
|
+
ecosystemService: EcosystemService;
|
|
7
|
+
correlator: CrossBrainCorrelator;
|
|
8
|
+
}
|
|
9
|
+
export declare function createHubDashboard(options: HubDashboardOptions): DashboardServer;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { DashboardServer } from './server.js';
|
|
4
|
+
export function createHubDashboard(options) {
|
|
5
|
+
const { port, ecosystemService, correlator } = options;
|
|
6
|
+
const htmlPath = path.resolve(path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1')), '../../hub-dashboard.html');
|
|
7
|
+
return new DashboardServer({
|
|
8
|
+
port,
|
|
9
|
+
getDashboardHtml: () => {
|
|
10
|
+
try {
|
|
11
|
+
const template = fs.readFileSync(htmlPath, 'utf-8');
|
|
12
|
+
const health = correlator.getHealth();
|
|
13
|
+
const correlations = correlator.getCorrelations();
|
|
14
|
+
const timeline = correlator.getTimeline(20);
|
|
15
|
+
const activeBrains = correlator.getActiveBrains();
|
|
16
|
+
return template
|
|
17
|
+
.replace(/\{\{HEALTH_SCORE\}\}/g, String(health.score))
|
|
18
|
+
.replace(/\{\{HEALTH_STATUS\}\}/g, health.status)
|
|
19
|
+
.replace(/\{\{ACTIVE_BRAINS\}\}/g, String(health.activeBrains))
|
|
20
|
+
.replace(/\{\{TOTAL_EVENTS\}\}/g, String(health.totalEvents))
|
|
21
|
+
.replace(/\{\{TOTAL_CORRELATIONS\}\}/g, String(health.correlations))
|
|
22
|
+
.replace('{{CORRELATIONS_JSON}}', JSON.stringify(correlations))
|
|
23
|
+
.replace('{{TIMELINE_JSON}}', JSON.stringify(timeline))
|
|
24
|
+
.replace('{{ACTIVE_BRAINS_JSON}}', JSON.stringify(activeBrains))
|
|
25
|
+
.replace('{{ALERTS_JSON}}', JSON.stringify(health.alerts));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return '<html><body><h1>Hub Dashboard HTML not found</h1></body></html>';
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
getStats: () => {
|
|
32
|
+
const health = correlator.getHealth();
|
|
33
|
+
return {
|
|
34
|
+
...health,
|
|
35
|
+
activeBrainNames: correlator.getActiveBrains(),
|
|
36
|
+
correlations: correlator.getCorrelations(),
|
|
37
|
+
timeline: correlator.getTimeline(20),
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=hub-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-server.js","sourceRoot":"","sources":["../../src/dashboard/hub-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAU9C,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAEvD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,EAC5E,0BAA0B,CAC3B,CAAC;IAEF,OAAO,IAAI,eAAe,CAAC;QACzB,IAAI;QACJ,gBAAgB,EAAE,GAAG,EAAE;YACrB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC;gBACtC,MAAM,YAAY,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC;gBAClD,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC;gBAElD,OAAO,QAAQ;qBACZ,OAAO,CAAC,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;qBACtD,OAAO,CAAC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;qBAChD,OAAO,CAAC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;qBAC9D,OAAO,CAAC,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;qBAC5D,OAAO,CAAC,6BAA6B,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;qBACnE,OAAO,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;qBAC9D,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;qBACtD,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;qBAC/D,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,iEAAiE,CAAC;YAC3E,CAAC;QACH,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC;YACtC,OAAO;gBACL,GAAG,MAAM;gBACT,gBAAgB,EAAE,UAAU,CAAC,eAAe,EAAE;gBAC9C,YAAY,EAAE,UAAU,CAAC,eAAe,EAAE;gBAC1C,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;aACrC,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CrossBrainCorrelator, Correlation, CorrelatorEvent, EcosystemHealth } from '../cross-brain/correlator.js';
|
|
2
|
+
import type { CrossBrainClient } from '../cross-brain/client.js';
|
|
3
|
+
export interface BrainStatus {
|
|
4
|
+
name: string;
|
|
5
|
+
available: boolean;
|
|
6
|
+
version?: string;
|
|
7
|
+
uptime?: number;
|
|
8
|
+
pid?: number;
|
|
9
|
+
methods?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface EcosystemStatus {
|
|
12
|
+
brains: BrainStatus[];
|
|
13
|
+
health: EcosystemHealth;
|
|
14
|
+
correlations: Correlation[];
|
|
15
|
+
recentEvents: CorrelatorEvent[];
|
|
16
|
+
}
|
|
17
|
+
export interface AggregatedAnalytics {
|
|
18
|
+
brain?: {
|
|
19
|
+
errors: number;
|
|
20
|
+
solutions: number;
|
|
21
|
+
modules: number;
|
|
22
|
+
};
|
|
23
|
+
trading?: {
|
|
24
|
+
trades: number;
|
|
25
|
+
winRate: number;
|
|
26
|
+
signals: number;
|
|
27
|
+
};
|
|
28
|
+
marketing?: {
|
|
29
|
+
posts: number;
|
|
30
|
+
campaigns: number;
|
|
31
|
+
engagement: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare class EcosystemService {
|
|
35
|
+
private correlator;
|
|
36
|
+
private crossBrain;
|
|
37
|
+
private logger;
|
|
38
|
+
constructor(correlator: CrossBrainCorrelator, crossBrain: CrossBrainClient);
|
|
39
|
+
/**
|
|
40
|
+
* Get the full ecosystem status: all peer brains, health, correlations, and recent events.
|
|
41
|
+
*/
|
|
42
|
+
getStatus(): Promise<EcosystemStatus>;
|
|
43
|
+
/**
|
|
44
|
+
* Get correlations, optionally filtered by minimum strength.
|
|
45
|
+
*/
|
|
46
|
+
getCorrelations(minStrength?: number): Correlation[];
|
|
47
|
+
/**
|
|
48
|
+
* Get the event timeline, optionally limited to the most recent N entries.
|
|
49
|
+
*/
|
|
50
|
+
getTimeline(limit?: number): CorrelatorEvent[];
|
|
51
|
+
/**
|
|
52
|
+
* Get the current ecosystem health assessment.
|
|
53
|
+
*/
|
|
54
|
+
getHealth(): EcosystemHealth;
|
|
55
|
+
/**
|
|
56
|
+
* Aggregate analytics from all peer brains.
|
|
57
|
+
* Each peer is queried independently; offline peers are silently skipped.
|
|
58
|
+
*/
|
|
59
|
+
getAggregatedAnalytics(): Promise<AggregatedAnalytics>;
|
|
60
|
+
/**
|
|
61
|
+
* Record a cross-brain event in the correlator.
|
|
62
|
+
*/
|
|
63
|
+
recordEvent(source: string, event: string, data: unknown): void;
|
|
64
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { getLogger } from '../utils/logger.js';
|
|
2
|
+
export class EcosystemService {
|
|
3
|
+
correlator;
|
|
4
|
+
crossBrain;
|
|
5
|
+
logger = getLogger();
|
|
6
|
+
constructor(correlator, crossBrain) {
|
|
7
|
+
this.correlator = correlator;
|
|
8
|
+
this.crossBrain = crossBrain;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get the full ecosystem status: all peer brains, health, correlations, and recent events.
|
|
12
|
+
*/
|
|
13
|
+
async getStatus() {
|
|
14
|
+
const responses = await this.crossBrain.broadcast('status');
|
|
15
|
+
const brains = responses.map((r) => {
|
|
16
|
+
const data = r.result;
|
|
17
|
+
return {
|
|
18
|
+
name: r.name,
|
|
19
|
+
available: true,
|
|
20
|
+
version: data?.version,
|
|
21
|
+
uptime: data?.uptime,
|
|
22
|
+
pid: data?.pid,
|
|
23
|
+
methods: data?.methods,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
// Mark peers that didn't respond as unavailable
|
|
27
|
+
const respondedNames = new Set(brains.map((b) => b.name));
|
|
28
|
+
for (const peerName of this.crossBrain.getPeerNames()) {
|
|
29
|
+
if (!respondedNames.has(peerName)) {
|
|
30
|
+
brains.push({ name: peerName, available: false });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const health = this.correlator.getHealth();
|
|
34
|
+
const correlations = this.correlator.getCorrelations();
|
|
35
|
+
const allEvents = this.correlator.getTimeline();
|
|
36
|
+
const recentEvents = allEvents.slice(-20);
|
|
37
|
+
return { brains, health, correlations, recentEvents };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get correlations, optionally filtered by minimum strength.
|
|
41
|
+
*/
|
|
42
|
+
getCorrelations(minStrength) {
|
|
43
|
+
return this.correlator.getCorrelations(minStrength);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the event timeline, optionally limited to the most recent N entries.
|
|
47
|
+
*/
|
|
48
|
+
getTimeline(limit) {
|
|
49
|
+
return this.correlator.getTimeline(limit);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the current ecosystem health assessment.
|
|
53
|
+
*/
|
|
54
|
+
getHealth() {
|
|
55
|
+
return this.correlator.getHealth();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Aggregate analytics from all peer brains.
|
|
59
|
+
* Each peer is queried independently; offline peers are silently skipped.
|
|
60
|
+
*/
|
|
61
|
+
async getAggregatedAnalytics() {
|
|
62
|
+
const analytics = {};
|
|
63
|
+
const [brainResult, tradingResult, marketingResult] = await Promise.all([
|
|
64
|
+
this.crossBrain.query('brain', 'analytics.summary'),
|
|
65
|
+
this.crossBrain.query('trading-brain', 'analytics.summary'),
|
|
66
|
+
this.crossBrain.query('marketing-brain', 'analytics.summary'),
|
|
67
|
+
]);
|
|
68
|
+
if (brainResult != null) {
|
|
69
|
+
const data = brainResult;
|
|
70
|
+
analytics.brain = {
|
|
71
|
+
errors: data.errors ?? 0,
|
|
72
|
+
solutions: data.solutions ?? 0,
|
|
73
|
+
modules: data.modules ?? 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (tradingResult != null) {
|
|
77
|
+
const data = tradingResult;
|
|
78
|
+
analytics.trading = {
|
|
79
|
+
trades: data.trades ?? 0,
|
|
80
|
+
winRate: data.winRate ?? 0,
|
|
81
|
+
signals: data.signals ?? 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (marketingResult != null) {
|
|
85
|
+
const data = marketingResult;
|
|
86
|
+
analytics.marketing = {
|
|
87
|
+
posts: data.posts ?? 0,
|
|
88
|
+
campaigns: data.campaigns ?? 0,
|
|
89
|
+
engagement: data.engagement ?? 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
this.logger.debug('Aggregated analytics collected', {
|
|
93
|
+
hasBrain: analytics.brain != null,
|
|
94
|
+
hasTrading: analytics.trading != null,
|
|
95
|
+
hasMarketing: analytics.marketing != null,
|
|
96
|
+
});
|
|
97
|
+
return analytics;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Record a cross-brain event in the correlator.
|
|
101
|
+
*/
|
|
102
|
+
recordEvent(source, event, data) {
|
|
103
|
+
this.correlator.recordEvent(source, event, data);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/ecosystem/service.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export { encodeMessage, MessageDecoder } from './ipc/protocol.js';
|
|
|
9
9
|
export { IpcServer } from './ipc/server.js';
|
|
10
10
|
export type { IpcRouter } from './ipc/server.js';
|
|
11
11
|
export { IpcClient } from './ipc/client.js';
|
|
12
|
+
export { validateParams, withValidation } from './ipc/validation.js';
|
|
13
|
+
export type { ValidationOptions } from './ipc/validation.js';
|
|
14
|
+
export { IpcError, ValidationError, NotFoundError, TimeoutError, ServiceUnavailableError } from './ipc/errors.js';
|
|
12
15
|
export { startMcpServer } from './mcp/server.js';
|
|
13
16
|
export type { McpServerOptions } from './mcp/server.js';
|
|
14
17
|
export { McpHttpServer } from './mcp/http-server.js';
|
|
@@ -16,6 +19,8 @@ export type { McpHttpServerOptions } from './mcp/http-server.js';
|
|
|
16
19
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
20
|
export { BaseApiServer } from './api/server.js';
|
|
18
21
|
export type { ApiServerOptions, RouteDefinition } from './api/server.js';
|
|
22
|
+
export { RateLimiter, readBodyWithLimit, applySecurityHeaders } from './api/middleware.js';
|
|
23
|
+
export type { RateLimitConfig, SizeLimitConfig, SecurityHeadersConfig } from './api/middleware.js';
|
|
19
24
|
export { wilsonScore } from './math/wilson-score.js';
|
|
20
25
|
export { timeDecayFactor } from './math/time-decay.js';
|
|
21
26
|
export { deepMerge, loadConfigFile } from './config/loader.js';
|
|
@@ -36,9 +41,15 @@ export type { MemoryRecord, SessionRecord, MemoryCategory, MemorySource, Session
|
|
|
36
41
|
export { BaseMemoryEngine } from './memory/base-memory-engine.js';
|
|
37
42
|
export { DashboardServer } from './dashboard/server.js';
|
|
38
43
|
export type { DashboardServerOptions } from './dashboard/server.js';
|
|
44
|
+
export { createHubDashboard } from './dashboard/hub-server.js';
|
|
45
|
+
export type { HubDashboardOptions } from './dashboard/hub-server.js';
|
|
39
46
|
export { CrossBrainClient } from './cross-brain/client.js';
|
|
40
47
|
export type { BrainPeer } from './cross-brain/client.js';
|
|
41
48
|
export { CrossBrainNotifier } from './cross-brain/notifications.js';
|
|
42
49
|
export type { CrossBrainEvent } from './cross-brain/notifications.js';
|
|
43
50
|
export { CrossBrainSubscriptionManager } from './cross-brain/subscription.js';
|
|
44
51
|
export type { EventSubscription } from './cross-brain/subscription.js';
|
|
52
|
+
export { CrossBrainCorrelator } from './cross-brain/correlator.js';
|
|
53
|
+
export type { CorrelatorEvent, Correlation, EcosystemHealth, CorrelatorConfig } from './cross-brain/correlator.js';
|
|
54
|
+
export { EcosystemService } from './ecosystem/service.js';
|
|
55
|
+
export type { BrainStatus, EcosystemStatus, AggregatedAnalytics } from './ecosystem/service.js';
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { createConnection } from './db/connection.js';
|
|
|
9
9
|
export { encodeMessage, MessageDecoder } from './ipc/protocol.js';
|
|
10
10
|
export { IpcServer } from './ipc/server.js';
|
|
11
11
|
export { IpcClient } from './ipc/client.js';
|
|
12
|
+
export { validateParams, withValidation } from './ipc/validation.js';
|
|
13
|
+
export { IpcError, ValidationError, NotFoundError, TimeoutError, ServiceUnavailableError } from './ipc/errors.js';
|
|
12
14
|
// ── MCP ────────────────────────────────────────────────────
|
|
13
15
|
export { startMcpServer } from './mcp/server.js';
|
|
14
16
|
export { McpHttpServer } from './mcp/http-server.js';
|
|
@@ -16,6 +18,7 @@ export { McpHttpServer } from './mcp/http-server.js';
|
|
|
16
18
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
19
|
// ── API ────────────────────────────────────────────────────
|
|
18
20
|
export { BaseApiServer } from './api/server.js';
|
|
21
|
+
export { RateLimiter, readBodyWithLimit, applySecurityHeaders } from './api/middleware.js';
|
|
19
22
|
// ── Math ───────────────────────────────────────────────────
|
|
20
23
|
export { wilsonScore } from './math/wilson-score.js';
|
|
21
24
|
export { timeDecayFactor } from './math/time-decay.js';
|
|
@@ -34,8 +37,12 @@ export { BaseEmbeddingEngine } from './embeddings/engine.js';
|
|
|
34
37
|
export { BaseMemoryEngine } from './memory/base-memory-engine.js';
|
|
35
38
|
// ── Dashboard ────────────────────────────────────────────
|
|
36
39
|
export { DashboardServer } from './dashboard/server.js';
|
|
40
|
+
export { createHubDashboard } from './dashboard/hub-server.js';
|
|
37
41
|
// ── Cross-Brain ────────────────────────────────────────────
|
|
38
42
|
export { CrossBrainClient } from './cross-brain/client.js';
|
|
39
43
|
export { CrossBrainNotifier } from './cross-brain/notifications.js';
|
|
40
44
|
export { CrossBrainSubscriptionManager } from './cross-brain/subscription.js';
|
|
45
|
+
export { CrossBrainCorrelator } from './cross-brain/correlator.js';
|
|
46
|
+
// ── Ecosystem ──────────────────────────────────────────────
|
|
47
|
+
export { EcosystemService } from './ecosystem/service.js';
|
|
41
48
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAElH,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,8DAA8D;AAC9D,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtH,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3F,8DAA8D;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQ/D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAU7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,4DAA4D;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for IPC operations.
|
|
3
|
+
*/
|
|
4
|
+
export declare class IpcError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly statusCode: number;
|
|
7
|
+
constructor(message: string, code: string, statusCode?: number);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when IPC params fail validation.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ValidationError extends IpcError {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Thrown when a requested method or resource is not found.
|
|
17
|
+
*/
|
|
18
|
+
export declare class NotFoundError extends IpcError {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when an IPC operation times out.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TimeoutError extends IpcError {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Thrown when a required service is not available.
|
|
29
|
+
*/
|
|
30
|
+
export declare class ServiceUnavailableError extends IpcError {
|
|
31
|
+
constructor(message?: string);
|
|
32
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for IPC operations.
|
|
3
|
+
*/
|
|
4
|
+
export class IpcError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
statusCode;
|
|
7
|
+
constructor(message, code, statusCode = 400) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'IpcError';
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.statusCode = statusCode;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when IPC params fail validation.
|
|
16
|
+
*/
|
|
17
|
+
export class ValidationError extends IpcError {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message, 'VALIDATION_ERROR', 400);
|
|
20
|
+
this.name = 'ValidationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Thrown when a requested method or resource is not found.
|
|
25
|
+
*/
|
|
26
|
+
export class NotFoundError extends IpcError {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message, 'NOT_FOUND', 404);
|
|
29
|
+
this.name = 'NotFoundError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Thrown when an IPC operation times out.
|
|
34
|
+
*/
|
|
35
|
+
export class TimeoutError extends IpcError {
|
|
36
|
+
constructor(message = 'Operation timed out') {
|
|
37
|
+
super(message, 'TIMEOUT', 408);
|
|
38
|
+
this.name = 'TimeoutError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Thrown when a required service is not available.
|
|
43
|
+
*/
|
|
44
|
+
export class ServiceUnavailableError extends IpcError {
|
|
45
|
+
constructor(message = 'Service unavailable') {
|
|
46
|
+
super(message, 'SERVICE_UNAVAILABLE', 503);
|
|
47
|
+
this.name = 'ServiceUnavailableError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=errors.js.map
|