getPrompt method
Build the prompt content for this command.
Implementation
@override
Future<List<ContentBlock>> getPrompt(
String args,
ToolUseContext context,
) async {
// Scan sessions, aggregate data, and generate insights.
final scannedSessions = await scanAllSessions();
final totalSessionsScanned = scannedSessions.length;
// Load cached session metas and identify uncached sessions.
final allMetas = <SessionMeta>[];
final uncachedSessions = <LiteSessionInfo>[];
const maxSessionsToLoad = 200;
for (final sessionInfo in scannedSessions) {
final cached = await loadCachedSessionMeta(sessionInfo.sessionId);
if (cached != null) {
allMetas.add(cached);
} else if (uncachedSessions.length < maxSessionsToLoad) {
uncachedSessions.add(sessionInfo);
}
}
// Deduplicate session branches.
final deduplicated = deduplicateSessionBranches(allMetas);
// Filter substantive sessions.
final substantive = deduplicated.where(isSubstantiveSession).toList();
// Load cached facets.
final facets = <String, SessionFacets>{};
for (final meta in substantive) {
final cached = await loadCachedFacets(meta.sessionId);
if (cached != null) {
facets[meta.sessionId] = cached;
}
}
// Filter out minimal sessions.
final nonMinimal = substantive
.where((s) => !isMinimalSession(s.sessionId, facets))
.toList();
final substantiveFacets = <String, SessionFacets>{};
for (final entry in facets.entries) {
if (!isMinimalSession(entry.key, facets)) {
substantiveFacets[entry.key] = entry.value;
}
}
// Aggregate data.
final aggregated = aggregateData(nonMinimal, substantiveFacets);
aggregated.totalSessionsScanned = totalSessionsScanned;
// Build stats line.
final sessionLabel =
aggregated.totalSessionsScanned != null &&
aggregated.totalSessionsScanned! > aggregated.totalSessions
? '${aggregated.totalSessionsScanned} sessions total, '
'${aggregated.totalSessions} analyzed'
: '${aggregated.totalSessions} sessions';
final stats = [
sessionLabel,
'${aggregated.totalMessages} messages',
'${aggregated.totalDurationHours.round()}h',
'${aggregated.gitCommits} commits',
].join(' . ');
final htmlPath = p.join(getDataDir(), 'report.html');
final reportUrl = 'file://$htmlPath';
return [
TextBlock(
'The user just ran /insights to generate a usage report analyzing '
'their Neomage sessions.\n\n'
'Stats: $stats\n'
'Date range: ${aggregated.dateRange.start} to ${aggregated.dateRange.end}\n'
'Sessions with facets: ${aggregated.sessionsWithFacets}\n'
'Report URL: $reportUrl\n\n'
'Summarize the session analysis for the user. Include:\n'
'- Total sessions and messages\n'
'- Top languages used: ${_topEntries(aggregated.languages, 3)}\n'
'- Top tools used: ${_topEntries(aggregated.toolCounts, 3)}\n'
'- Top goals: ${_topEntries(aggregated.goalCategories, 3)}\n'
'- Outcomes: ${_topEntries(aggregated.outcomes, 3)}\n'
'- Friction types: ${_topEntries(aggregated.friction, 3)}\n'
'- Days active: ${aggregated.daysActive}\n'
'- Messages per day: ${aggregated.messagesPerDay}\n'
'- Lines added/removed: +${aggregated.totalLinesAdded}/-${aggregated.totalLinesRemoved}\n'
'- Multi-clauding events: ${aggregated.multiClauding.overlapEvents}\n\n'
'End with: "Your shareable insights report is ready: $reportUrl"\n'
'Ask if they want to dig into any section.',
),
];
}