feat(brain): aggregator — node heat, distributions, redirect rate (+4 tests)
This commit is contained in:
@@ -137,6 +137,41 @@ export function filterEpisodes(episodes, filter = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
// Aggregates a list of episodes into dashboard metrics.
|
||||
export function aggregate(episodes) {
|
||||
const nodeHeat = {};
|
||||
const pathType = {};
|
||||
const outcome = {};
|
||||
const classification = {};
|
||||
const economy = {};
|
||||
let totalErrors = 0;
|
||||
let totalRetries = 0;
|
||||
let redirects = 0;
|
||||
for (const e of episodes) {
|
||||
for (const id of attributeNodes(e).nodeIds) nodeHeat[id] = (nodeHeat[id] || 0) + 1;
|
||||
if (e.pathType) pathType[e.pathType] = (pathType[e.pathType] || 0) + 1;
|
||||
outcome[e.outcome] = (outcome[e.outcome] || 0) + 1;
|
||||
if (e.taskClassification) classification[e.taskClassification] = (classification[e.taskClassification] || 0) + 1;
|
||||
const lvl = e.environment ? e.environment.economy_level : null;
|
||||
const key = lvl == null ? 'n/a' : String(lvl);
|
||||
economy[key] = (economy[key] || 0) + 1;
|
||||
totalErrors += e.errorCount;
|
||||
totalRetries += e.retryCount;
|
||||
if (e.decisionProvenance && e.decisionProvenance.kind === 'user_directed_method') redirects++;
|
||||
}
|
||||
return {
|
||||
nodeHeat,
|
||||
pathType,
|
||||
outcome,
|
||||
classification,
|
||||
economy,
|
||||
totalErrors,
|
||||
totalRetries,
|
||||
redirectRate: episodes.length ? redirects / episodes.length : 0,
|
||||
count: episodes.length,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseEpisodes(text) {
|
||||
const episodes = [];
|
||||
let skipped = 0;
|
||||
|
||||
Reference in New Issue
Block a user