From f335d3762b4ced576912470c123070f8f3631a38 Mon Sep 17 00:00:00 2001 From: Nexus Dev Date: Wed, 1 Apr 2026 23:01:03 +0000 Subject: [PATCH] feat(25-00): add shared types, validators, and test stubs for file system - Add ChatFile, ChatFileReference, ChatFileUploadResponse, ChatFileListResponse interfaces to types/chat.ts - Add optional files?: ChatFile[] field to ChatMessage interface - Add uploadChatFileSchema and createFileReferenceSchema Zod validators to validators/chat.ts - Re-export all new types and validators from shared/src/index.ts - Create test stubs for chat-file-service.test.ts and chat-file-routes.test.ts with it.todo() entries --- packages/shared/src/index.ts | 8 +++++ packages/shared/src/types/chat.ts | 36 +++++++++++++++++++ packages/shared/src/validators/chat.ts | 15 ++++++++ server/src/__tests__/chat-file-routes.test.ts | 10 ++++++ .../src/__tests__/chat-file-service.test.ts | 9 +++++ 5 files changed, 78 insertions(+) create mode 100644 server/src/__tests__/chat-file-routes.test.ts create mode 100644 server/src/__tests__/chat-file-service.test.ts diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 9e7906bf..a986dd78 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -595,12 +595,16 @@ export { handoffSchema, searchMessagesSchema, branchConversationSchema, + uploadChatFileSchema, + createFileReferenceSchema, type CreateConversation, type UpdateConversation, type CreateMessage, type Handoff, type SearchMessages, type BranchConversation, + type UploadChatFile, + type CreateFileReference, } from "./validators/index.js"; export type { @@ -615,6 +619,10 @@ export type { ChatBookmarkWithMessage, ChatBookmarkListResponse, ChatBookmarkToggleResponse, + ChatFile, + ChatFileReference, + ChatFileUploadResponse, + ChatFileListResponse, } from "./types/chat.js"; export { API_PREFIX, API } from "./api.js"; diff --git a/packages/shared/src/types/chat.ts b/packages/shared/src/types/chat.ts index b015cd1b..dd1acd5d 100644 --- a/packages/shared/src/types/chat.ts +++ b/packages/shared/src/types/chat.ts @@ -25,6 +25,41 @@ export interface ChatConversationListItem { branchFromMessageId: string | null; } +export interface ChatFile { + id: string; + companyId: string; + conversationId: string | null; + messageId: string | null; + filename: string; + originalFilename: string; + mimeType: string; + sizeBytes: number; + objectKey: string; + sha256: string; + source: "user_upload" | "agent_generated"; + category: "image" | "document" | "code" | "other" | null; + projectId: string | null; + createdAt: string; + updatedAt: string; +} + +export interface ChatFileReference { + id: string; + fileId: string; + conversationId: string; + messageId: string | null; + createdAt: string; +} + +export interface ChatFileUploadResponse { + file: ChatFile; + contentPath: string; +} + +export interface ChatFileListResponse { + items: ChatFile[]; +} + export interface ChatMessage { id: string; conversationId: string; @@ -34,6 +69,7 @@ export interface ChatMessage { messageType: string | null; createdAt: string; updatedAt: string | null; + files?: ChatFile[]; } export interface ChatConversationListResponse { diff --git a/packages/shared/src/validators/chat.ts b/packages/shared/src/validators/chat.ts index 91a17f5c..98b15a43 100644 --- a/packages/shared/src/validators/chat.ts +++ b/packages/shared/src/validators/chat.ts @@ -45,3 +45,18 @@ export const branchConversationSchema = z.object({ export type SearchMessages = z.infer; export type BranchConversation = z.infer; + +export const uploadChatFileSchema = z.object({ + conversationId: z.string().uuid().optional(), + messageId: z.string().uuid().optional(), + source: z.enum(["user_upload", "agent_generated"]).default("user_upload"), + projectId: z.string().uuid().optional(), +}); + +export const createFileReferenceSchema = z.object({ + fileId: z.string().uuid(), + messageId: z.string().uuid().optional(), +}); + +export type UploadChatFile = z.infer; +export type CreateFileReference = z.infer; diff --git a/server/src/__tests__/chat-file-routes.test.ts b/server/src/__tests__/chat-file-routes.test.ts new file mode 100644 index 00000000..e01aa30b --- /dev/null +++ b/server/src/__tests__/chat-file-routes.test.ts @@ -0,0 +1,10 @@ +import { describe, it } from "vitest"; + +describe("chatFileRoutes", () => { + it.todo("POST /conversations/:id/files uploads a file and returns 201"); + it.todo("GET /conversations/:id/files lists files for conversation"); + it.todo("GET /files/:fileId/content serves file content"); + it.todo("POST /files/:fileId/references creates a cross-conversation reference"); + it.todo("rejects upload when file exceeds size limit"); + it.todo("rejects upload when content type is not allowed"); +}); diff --git a/server/src/__tests__/chat-file-service.test.ts b/server/src/__tests__/chat-file-service.test.ts new file mode 100644 index 00000000..1725cf02 --- /dev/null +++ b/server/src/__tests__/chat-file-service.test.ts @@ -0,0 +1,9 @@ +import { describe, it } from "vitest"; + +describe("chatFileService", () => { + it.todo("creates a file record after upload"); + it.todo("lists files for a conversation"); + it.todo("lists files for a message"); + it.todo("creates a file reference in another conversation"); + it.todo("returns file with contentPath"); +});