Conversation
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
…-820c-2ebb78495a45 Implement document upload and management system for AI agents
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
…tion improvements Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
…% reduction) Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
Co-authored-by: tikazyq <3393101+tikazyq@users.noreply.github.com>
…-aa10-dc3033ec42f1 Complete TypeORM to Prisma migration with functional services and smart fallback system
…ror handling in PrismaAuthService
…nd improve error handling
…ing Prisma migration
… and streamline database interactions
- Introduced `PrismaServiceBase` to encapsulate shared logic for Prisma services. - Updated `PrismaDevlogService` and `PrismaProjectService` to extend from `PrismaServiceBase`. - Implemented singleton pattern with TTL-based cleanup for service instances. - Simplified Prisma client initialization and fallback handling. - Removed redundant initialization logic from individual services. - Enhanced lifecycle hooks for better extensibility and maintainability.
…onsistency and clarity
…d metadata management
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull Request Overview
This PR implements a comprehensive migration from TypeORM to Prisma for database management, replacing multiple environment variables with a single DATABASE_URL configuration. The migration includes new Prisma services, schema definitions, and document management capabilities while maintaining API compatibility.
Key Changes:
- Complete migration from TypeORM entities to Prisma schema
- Simplified database configuration using only
DATABASE_URL - New document management system with file upload and type detection
- Prisma-based service implementations with fallback mode support
Reviewed Changes
Copilot reviewed 81 out of 83 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
prisma/schema.prisma |
New Prisma schema defining all database models with PostgreSQL optimizations |
prisma/migrations/ |
Database migration files for schema setup and enum refactoring |
packages/core/src/services/prisma-*.ts |
New Prisma-based service implementations replacing TypeORM services |
packages/core/src/utils/prisma-config.ts |
New Prisma client configuration replacing TypeORM config |
packages/mcp/src/tools/document-tools.ts |
New MCP tools for document management operations |
turbo.json |
Simplified environment variables using only DATABASE_URL |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| model ChatSession { | ||
| id String @id | ||
| agent String // AgentType as string | ||
| timestamp String // ISO string |
There was a problem hiding this comment.
Using String for timestamps instead of DateTime reduces type safety and requires manual conversion. Consider using DateTime type with @db.Timestamptz for better type safety and automatic timestamp handling.
| timestamp String // ISO string | |
| timestamp DateTime @db.Timestamptz // Timestamp with timezone |
| const prismaModule = await import('@prisma/client'); | ||
| const configModule = await import('../utils/prisma-config.js'); |
There was a problem hiding this comment.
Dynamic imports in initialization could impact performance. Consider using static imports or lazy loading patterns since Prisma client is a core dependency.
| if (this.isFallbackMode) { | ||
| console.warn('[DocumentService] uploadDocument() called in fallback mode - returning mock document'); | ||
|
|
||
| const documentId = `doc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; |
There was a problem hiding this comment.
ID generation is duplicated across multiple places. Consider using the existing generateDocumentId utility from id-generator.ts for consistency.
| // For getDocument, we need to find which devlog contains the document | ||
| // This is a limitation of the current API design - we'll try a simple approach | ||
| // by searching through recent devlogs | ||
| const devlogs = await this.apiClient.listDevlogs({ | ||
| page: 1, | ||
| limit: 20, | ||
| sortBy: 'updatedAt', | ||
| sortOrder: 'desc' | ||
| }); | ||
|
|
||
| let document = null; | ||
| for (const devlog of devlogs.items || []) { | ||
| try { | ||
| document = await this.apiClient.getDocument(devlog.id!, args.documentId); | ||
| break; | ||
| } catch (err) { | ||
| // Document not found in this devlog, continue searching | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| if (!document) { | ||
| return this.toStandardResponse(false, null, `Document ${args.documentId} not found`); | ||
| } | ||
|
|
||
| return this.toStandardResponse( | ||
| true, | ||
| document, | ||
| `Retrieved document: ${document.originalName || args.documentId}`, |
There was a problem hiding this comment.
Searching through multiple devlogs sequentially to find a document could be inefficient. Consider adding a search endpoint that can locate documents directly by ID across all devlogs.
| // For getDocument, we need to find which devlog contains the document | |
| // This is a limitation of the current API design - we'll try a simple approach | |
| // by searching through recent devlogs | |
| const devlogs = await this.apiClient.listDevlogs({ | |
| page: 1, | |
| limit: 20, | |
| sortBy: 'updatedAt', | |
| sortOrder: 'desc' | |
| }); | |
| let document = null; | |
| for (const devlog of devlogs.items || []) { | |
| try { | |
| document = await this.apiClient.getDocument(devlog.id!, args.documentId); | |
| break; | |
| } catch (err) { | |
| // Document not found in this devlog, continue searching | |
| continue; | |
| } | |
| } | |
| if (!document) { | |
| return this.toStandardResponse(false, null, `Document ${args.documentId} not found`); | |
| } | |
| return this.toStandardResponse( | |
| true, | |
| document, | |
| `Retrieved document: ${document.originalName || args.documentId}`, | |
| // Use the searchDocuments endpoint to locate the document by ID across all devlogs | |
| const searchResult = await this.apiClient.searchDocuments({ documentId: args.documentId }); | |
| const foundDocument = searchResult.items && searchResult.items.length > 0 ? searchResult.items[0] : null; | |
| if (!foundDocument) { | |
| return this.toStandardResponse(false, null, `Document ${args.documentId} not found`); | |
| } | |
| return this.toStandardResponse( | |
| true, | |
| foundDocument, | |
| `Retrieved document: ${foundDocument.originalName || args.documentId}`, |
| const maxTextSize = 64 * 1024; // 64KB limit | ||
| return textContent.length > maxTextSize | ||
| ? textContent.substring(0, maxTextSize) + '...[truncated]' | ||
| : textContent; |
There was a problem hiding this comment.
Magic number 64KB should be extracted as a named constant. Also consider making this configurable since different environments may have different text size limits.
| this.JWT_SECRET = process.env.JWT_SECRET || 'fallback-secret-for-development'; | ||
|
|
||
| if (!process.env.JWT_SECRET && process.env.NODE_ENV === 'production') { | ||
| throw new Error('JWT_SECRET environment variable is required in production'); | ||
| } |
There was a problem hiding this comment.
The fallback JWT secret could be a security risk if accidentally used in production. Consider throwing an error immediately if JWT_SECRET is not set, regardless of environment.
| this.JWT_SECRET = process.env.JWT_SECRET || 'fallback-secret-for-development'; | |
| if (!process.env.JWT_SECRET && process.env.NODE_ENV === 'production') { | |
| throw new Error('JWT_SECRET environment variable is required in production'); | |
| } | |
| if (!process.env.JWT_SECRET) { | |
| throw new Error('JWT_SECRET environment variable is required'); | |
| } | |
| this.JWT_SECRET = process.env.JWT_SECRET; |
|
@copilot can you work on the suggestion? |
No description provided.