@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
87 lines • 3.42 kB
JavaScript
/** Bucket key for a score whose run named no agent (mirrors the governance run breakdown). */
const DEFAULT_AGENT_BUCKET = '(default)';
/** Mean of a bucket. Every caller below builds its buckets by pushing, so none is ever empty. */
function mean(values) {
let total = 0;
for (const value of values) {
total += value;
}
return total / values.length;
}
/** Rollup per scorer, worst mean first — the ordering that puts the problem at the top. */
export function summarizeByScorer(rows) {
const byScorer = new Map();
for (const row of rows) {
const bucket = byScorer.get(row.scorer) ?? { kind: row.kind, scores: [] };
bucket.scores.push(row.score);
byScorer.set(row.scorer, bucket);
}
const result = [];
for (const [scorer, bucket] of byScorer) {
result.push({
scorer,
kind: bucket.kind,
samples: bucket.scores.length,
meanScore: mean(bucket.scores),
minScore: Math.min(...bucket.scores),
maxScore: Math.max(...bucket.scores),
});
}
result.sort((left, right) => left.meanScore - right.meanScore || left.scorer.localeCompare(right.scorer));
return result;
}
/** Rollup per (agent, scorer) pair, worst mean first — which persona drags which signal down. */
export function summarizeByAgent(rows) {
const byPair = new Map();
for (const row of rows) {
const agentName = row.agentName ?? DEFAULT_AGENT_BUCKET;
const key = `${agentName} ${row.scorer}`;
const bucket = byPair.get(key) ?? { agentName, scorer: row.scorer, scores: [] };
bucket.scores.push(row.score);
byPair.set(key, bucket);
}
const result = [];
for (const bucket of byPair.values()) {
result.push({
agentName: bucket.agentName,
scorer: bucket.scorer,
samples: bucket.scores.length,
meanScore: mean(bucket.scores),
});
}
result.sort((left, right) => left.meanScore - right.meanScore ||
left.agentName.localeCompare(right.agentName) ||
left.scorer.localeCompare(right.scorer));
return result;
}
/** Daily mean per scorer, ascending by day then scorer — the "is it getting better" series. */
export function bucketScoreTrend(rows) {
const byDay = new Map();
for (const row of rows) {
const key = `${row.day} ${row.scorer}`;
const bucket = byDay.get(key) ?? { day: row.day, scorer: row.scorer, scores: [] };
bucket.scores.push(row.score);
byDay.set(key, bucket);
}
const result = [];
for (const bucket of byDay.values()) {
result.push({
day: bucket.day,
scorer: bucket.scorer,
samples: bucket.scores.length,
meanScore: mean(bucket.scores),
});
}
result.sort((left, right) => left.day.localeCompare(right.day) || left.scorer.localeCompare(right.scorer));
return result;
}
/**
* The lowest-scoring runs, worst first, capped at `limit` — the triage queue. Every scorer carries a
* `reason`, so this is the one view that answers "show me what went wrong" without a second read.
*/
export function worstScoredRuns(rows, limit) {
return [...rows]
.sort((left, right) => left.score - right.score || left.runId.localeCompare(right.runId))
.slice(0, limit);
}
//# sourceMappingURL=summarize.js.map