Files
vibn-frontend/app/api/projects/[projectId]/complete-history/route.ts

166 lines
5.2 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getApiUrl } from '@/lib/utils/api-url';
/**
* Complete Chronological History
* Returns ALL project data in a single chronological timeline
* Optimized for AI consumption - no truncation, no summaries
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ projectId: string }> }
) {
try {
const { projectId } = await params;
// Load all three data sources
const [contextRes, gitRes, activityRes, timelineRes] = await Promise.all([
fetch(getApiUrl(`/api/projects/${projectId}/context`, request)),
fetch(getApiUrl(`/api/projects/${projectId}/git-history`, request)),
fetch(getApiUrl(`/api/projects/${projectId}/activity`, request)),
fetch(getApiUrl(`/api/projects/${projectId}/timeline`, request))
]);
const context = contextRes.ok ? await contextRes.json() : null;
const git = gitRes.ok ? await gitRes.json() : null;
const activity = activityRes.ok ? await activityRes.json() : null;
const timeline = timelineRes.ok ? await timelineRes.json() : null;
// Build complete chronological event stream
const events: any[] = [];
// Add all Git commits as events
if (git?.commits) {
for (const commit of git.commits) {
events.push({
type: 'git_commit',
timestamp: new Date(commit.date).toISOString(),
date: commit.date.split(' ')[0],
data: {
hash: commit.hash,
author: commit.author,
message: commit.message,
filesChanged: commit.filesChanged,
insertions: commit.insertions,
deletions: commit.deletions
}
});
}
}
// Add all extension sessions as events
if (activity?.sessions) {
for (const session of activity.sessions) {
events.push({
type: 'extension_session',
timestamp: session.startTime,
date: new Date(session.startTime).toISOString().split('T')[0],
data: {
id: session.id,
startTime: session.startTime,
endTime: session.endTime,
duration: session.duration,
filesModified: session.filesModified,
conversationSummary: session.conversationSummary?.substring(0, 200),
conversationSnippets: (session.conversation || []).slice(0, 5).map((msg: any) => ({
role: msg.role,
message: msg.message?.substring(0, 100),
timestamp: msg.timestamp
}))
}
});
}
}
// Add Cursor conversations (from recent conversations in context)
if (context?.activity?.recentConversations) {
for (const conv of context.activity.recentConversations) {
events.push({
type: 'cursor_conversation',
timestamp: conv.createdAt,
date: new Date(conv.createdAt).toISOString().split('T')[0],
data: {
id: conv.id,
name: conv.name,
createdAt: conv.createdAt,
messageCount: conv.recentMessages?.length || 0,
recentMessages: conv.recentMessages?.map((msg: any) => ({
type: msg.type,
text: msg.text?.substring(0, 150),
createdAt: msg.createdAt
}))
}
});
}
}
// Sort everything chronologically
events.sort((a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
);
// Group by date for easier consumption
const eventsByDate: Record<string, any[]> = {};
for (const event of events) {
if (!eventsByDate[event.date]) {
eventsByDate[event.date] = [];
}
eventsByDate[event.date].push(event);
}
// Build response
const completeHistory = {
project: {
id: projectId,
name: context?.project?.name,
vision: context?.project?.vision,
githubRepo: context?.project?.githubRepo
},
summary: {
totalEvents: events.length,
dateRange: {
earliest: events[0]?.date,
latest: events[events.length - 1]?.date,
totalDays: Object.keys(eventsByDate).length
},
breakdown: {
gitCommits: events.filter(e => e.type === 'git_commit').length,
extensionSessions: events.filter(e => e.type === 'extension_session').length,
cursorConversations: events.filter(e => e.type === 'cursor_conversation').length
}
},
chronologicalEvents: events,
eventsByDate: Object.keys(eventsByDate)
.sort()
.map(date => ({
date,
dayOfWeek: new Date(date).toLocaleDateString('en-US', { weekday: 'long' }),
eventCount: eventsByDate[date].length,
events: eventsByDate[date]
})),
metadata: {
generatedAt: new Date().toISOString(),
dataComplete: true,
includesFullHistory: true
}
};
return NextResponse.json(completeHistory);
} catch (error) {
console.error('Error generating complete history:', error);
return NextResponse.json(
{
error: 'Failed to generate complete history',
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}