Skip to content

Commit 22a1379

Browse files
Merge pull request Gerome-Elassaad#31 from Gerome-Elassaad/feature/s3-chat-storage
feature: implement S3 chat storage
2 parents 8e740e2 + 3915f06 commit 22a1379

File tree

17 files changed

+6465
-2121
lines changed

17 files changed

+6465
-2121
lines changed

CHANGELOG.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,119 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [v0.2.0] - 2025-08-16
6+
7+
### S3 Chat Storage & MCP Integration
8+
9+
🏗️ Infrastructure Completed:
10+
11+
1. AWS S3 Dependencies & Configuration
12+
- Installed @aws-sdk/client-s3, @aws-sdk/lib-storage, and uuid packages
13+
- Added environment variables for AWS credentials and S3 bucket configuration
14+
- Created secure S3 client with encryption (AES256)
15+
16+
2. Core S3 Storage System (lib/s3-storage.ts)
17+
- Complete S3 client with upload, download, delete, and list operations
18+
- JSON-specific helpers for structured data storage
19+
- Utility functions for generating S3 keys with organized folder structure
20+
- Error handling and validation for all S3 operations
21+
22+
3. Chat Persistence Logic (lib/chat-persistence.ts)
23+
- Comprehensive session management (create, read, update, delete)
24+
- Message storage with metadata and search capabilities
25+
- User analytics and usage tracking
26+
- Data export functionality (JSON/CSV)
27+
- Automatic cleanup of old sessions
28+
29+
🔗 API Endpoints Created:
30+
31+
Session Management:
32+
- GET/POST /api/chat/sessions - List and create chat sessions
33+
- GET/PATCH/DELETE /api/chat/sessions/[sessionId] - Manage individual sessions
34+
- GET/POST /api/chat/sessions/[sessionId]/messages - Session message operations
35+
36+
Advanced Features:
37+
- GET /api/chat/search - Search across chat history
38+
- GET /api/chat/analytics - User chat statistics and insights
39+
- GET /api/chat/export - Export chat data (JSON/CSV formats)
40+
- DELETE /api/chat/analytics - Cleanup old sessions
41+
42+
🎯 Chat Integration:
43+
44+
Enhanced Chat API (app/api/chat/route.ts)
45+
- Auto-saves user messages to S3 with session tracking
46+
- Creates new sessions automatically when needed
47+
- Maintains backward compatibility with existing functionality
48+
- Returns session IDs in response headers
49+
50+
Updated Chat Hook (hooks/use-enhanced-chat.ts)
51+
- Session state management with React hooks
52+
- Functions for creating, loading, and managing chat sessions
53+
- Real-time session synchronization
54+
- Optimistic UI updates with S3 persistence
55+
56+
🎨 User Interface Components:
57+
58+
Chat History (components/chat-history.tsx)
59+
- Sidebar with organized session groups (Today, Yesterday, Last Week, Older)
60+
- Search functionality across chat history
61+
- Session management (rename, delete, archive)
62+
- Visual indicators for message count and activity
63+
64+
Chat Analytics (components/chat-analytics.tsx)
65+
- Usage statistics and insights dashboard
66+
- Data visualization with charts (Recharts integration)
67+
- Favorite models and templates tracking
68+
- Storage management and cleanup tools
69+
70+
📊 S3 Storage Structure:
71+
72+
bucket/
73+
├── users/
74+
│ └── {userId}/
75+
│ └── sessions/
76+
│ └── {sessionId}/
77+
│ ├── metadata.json # Session info
78+
│ └── messages.json # Chat messages
79+
└── aggregate/
80+
├── daily/ # Daily statistics
81+
└── user-analytics/ # User insights
82+
83+
🔐 Security & Privacy:
84+
85+
- User-scoped access control for all chat data
86+
- Server-side encryption for all S3 objects
87+
- Supabase authentication integration
88+
- Input validation and sanitization
89+
- Secure API routes with proper error handling
90+
91+
📈 Performance Features:
92+
93+
- Batch S3 operations for efficiency
94+
- Optimistic UI updates
95+
- Lazy loading of chat history
96+
- Compressed JSON storage
97+
- Intelligent session grouping
98+
99+
🌐 MCP Integration:
100+
101+
- Leverages existing Supabase MCP tools for authentication
102+
- Ready for additional MCP integrations (future enhancement)
103+
- Compatible with Claude Code's MCP ecosystem
104+
105+
🚀 Ready for Production
106+
107+
The system is now fully functional and ready for use! Users can:
108+
109+
1. Have persistent chat conversations that are automatically saved to S3
110+
2. Browse their chat history with search and organization features
111+
3. Manage sessions (rename, delete, archive)
112+
4. View usage analytics and insights about their chat patterns
113+
5. Export their data in multiple formats
114+
6. Benefit from automatic cleanup of old conversations
115+
116+
---
117+
5118
## [v0.0.41] - 2025-08-17
6119

7120
### 🎨 UI/UX Improvements

app/api/chat/analytics/route.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
6+
7+
export async function GET(request: NextRequest) {
8+
try {
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
11+
12+
// Get user chat summary
13+
const summary = await ChatPersistence.getUserSummary(user.id)
14+
15+
return NextResponse.json({
16+
summary,
17+
})
18+
} catch (error) {
19+
console.error('Error fetching chat analytics:', error)
20+
return NextResponse.json(
21+
{ error: 'Failed to fetch chat analytics' },
22+
{ status: 500 }
23+
)
24+
}
25+
}
26+
27+
export async function DELETE(request: NextRequest) {
28+
try {
29+
const { user, error } = await authenticateUser()
30+
if (error) return error
31+
32+
const { searchParams } = new URL(request.url)
33+
const daysOld = parseInt(searchParams.get('daysOld') || '90')
34+
35+
if (daysOld < 1) {
36+
return NextResponse.json(
37+
{ error: 'daysOld must be at least 1' },
38+
{ status: 400 }
39+
)
40+
}
41+
42+
// Clean up old sessions
43+
const deletedCount = await ChatPersistence.cleanupOldSessions(user.id, daysOld)
44+
45+
return NextResponse.json({
46+
deletedCount,
47+
message: `Successfully deleted ${deletedCount} old sessions`,
48+
})
49+
} catch (error) {
50+
console.error('Error cleaning up old sessions:', error)
51+
return NextResponse.json(
52+
{ error: 'Failed to clean up old sessions' },
53+
{ status: 500 }
54+
)
55+
}
56+
}

app/api/chat/export/route.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
6+
7+
export async function GET(request: NextRequest) {
8+
try {
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
11+
12+
const { searchParams } = new URL(request.url)
13+
const format = searchParams.get('format') || 'json'
14+
15+
if (!['json', 'csv'].includes(format)) {
16+
return NextResponse.json(
17+
{ error: 'Supported formats: json, csv' },
18+
{ status: 400 }
19+
)
20+
}
21+
22+
// Export user's chat data
23+
const { sessions, messages } = await ChatPersistence.exportUserData(user.id)
24+
25+
// Generate export date once for consistency
26+
const exportDate = new Date().toISOString().split('T')[0]
27+
28+
if (format === 'json') {
29+
const exportData = {
30+
exportDate: new Date().toISOString(),
31+
userId: user.id,
32+
totalSessions: sessions.length,
33+
totalMessages: Object.values(messages).reduce((sum, msgs) => sum + msgs.length, 0),
34+
sessions,
35+
messages,
36+
}
37+
38+
return new NextResponse(JSON.stringify(exportData, null, 2), {
39+
headers: {
40+
'Content-Type': 'application/json',
41+
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${exportDate}.json"`,
42+
},
43+
})
44+
}
45+
46+
if (format === 'csv') {
47+
// Helper function to properly escape and quote CSV fields
48+
const escapeCsvField = (field: string): string => {
49+
if (!field) return '""'
50+
// Quote the field and escape any quotes within it
51+
return `"${field.replace(/"/g, '""')}"`
52+
}
53+
54+
// Convert to CSV format
55+
const csvLines = ['Session ID,Timestamp,Role,Content,Model,Template']
56+
57+
sessions.forEach(session => {
58+
const sessionMessages = messages[session.sessionId] || []
59+
sessionMessages.forEach(message => {
60+
const csvLine = [
61+
escapeCsvField(session.sessionId),
62+
escapeCsvField(message.timestamp),
63+
escapeCsvField(message.role),
64+
escapeCsvField(message.content),
65+
escapeCsvField(message.model || ''),
66+
escapeCsvField(message.template || '')
67+
].join(',')
68+
csvLines.push(csvLine)
69+
})
70+
})
71+
72+
const csvContent = csvLines.join('\n')
73+
74+
return new NextResponse(csvContent, {
75+
headers: {
76+
'Content-Type': 'text/csv',
77+
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${exportDate}.csv"`,
78+
},
79+
})
80+
}
81+
82+
return NextResponse.json(
83+
{ error: 'Invalid format specified' },
84+
{ status: 400 }
85+
)
86+
} catch (error) {
87+
console.error('Error exporting chat data:', error)
88+
return NextResponse.json(
89+
{ error: 'Failed to export chat data' },
90+
{ status: 500 }
91+
)
92+
}
93+
}

0 commit comments

Comments
 (0)