(projectRoot, options = {})
| 10 | } |
| 11 | |
| 12 | function buildAgentReport(projectRoot, options = {}) { |
| 13 | const { limit = null } = options; |
| 14 | const paths = resolveTelemetryPaths(projectRoot); |
| 15 | const data = readJsonlDetailed(paths.agentRuns, { validator: validateAgentRunEvent }); |
| 16 | const relevant = limit ? data.entries.slice(-limit) : data.entries; |
| 17 | const counts = {}; |
| 18 | const completedDurations = []; |
| 19 | |
| 20 | for (const entry of relevant) { |
| 21 | counts[entry.event] = (counts[entry.event] || 0) + 1; |
| 22 | if (typeof entry.duration_ms === 'number' && (entry.event === 'agent-complete' || entry.event === 'agent-fail')) { |
| 23 | completedDurations.push(entry.duration_ms); |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | const recentRuns = relevant |
| 28 | .filter(entry => entry.event === 'agent-complete' || entry.event === 'agent-fail') |
| 29 | .slice(-10) |
| 30 | .map(entry => ({ |
| 31 | timestamp: entry.timestamp, |
| 32 | agent: entry.agent, |
| 33 | status: entry.status || entry.event, |
| 34 | duration_ms: entry.duration_ms, |
| 35 | })); |
| 36 | |
| 37 | const averageDurationMs = completedDurations.length > 0 |
| 38 | ? completedDurations.reduce((sum, value) => sum + value, 0) / completedDurations.length |
| 39 | : null; |
| 40 | |
| 41 | return { |
| 42 | kind: 'agent', |
| 43 | totalEntries: data.entries.length, |
| 44 | visibleEntries: relevant.length, |
| 45 | counts, |
| 46 | recentRuns, |
| 47 | averageDurationMs, |
| 48 | invalidCount: data.invalidCount, |
| 49 | invalidSummary: summarizeInvalid(data), |
| 50 | }; |
| 51 | } |
| 52 | |
| 53 | function buildHookReport(projectRoot) { |
| 54 | const paths = resolveTelemetryPaths(projectRoot); |
no test coverage detected