Complete reference for all TypeScript types in the MemexLLM frontend.
Types are organized by domain and shared across components, hooks, and API clients. All types are exported from lib/api/types.ts and lib/types.ts.
File: lib/types.ts
export type SourceType = "pdf" | "doc" | "image" | "video" | "audio" | "link" | "text" | "file";
export type SourceStatus = "pending" | "processing" | "completed" | "failed";
export interface Source {
id: string;
name: string;
type: SourceType;
status?: SourceStatus;
chunkCount?: number;
mimeType?: string;
errorMessage?: string | null;
preview?: string | null;
}File: lib/api/types.ts
export interface User {
id: string;
email: string;
is_active: boolean;
created_at: string;
}Configuration for RAG behavior per notebook.
export interface NotebookRAGSettings {
chunk_size?: number; // Text chunk size (default: 1000)
chunk_overlap?: number; // Chunk overlap (default: 200)
top_k_results?: number; // Chunks to retrieve (default: 30)
enable_query_fusion?: boolean; // Enable query expansion
fusion_num_queries?: number; // Number of query variations
use_hyde?: boolean; // Use HyDE for retrieval
enable_reranking?: boolean; // Enable result reranking
reranker_top_n?: number; // Chunks to rerank
default_alpha?: number; // Hybrid search balance (0-1)
use_sentence_window?: boolean; // Use sentence window retrieval
sentence_window_size?: number; // Window size in sentences
response_mode?: "compact" | "tree_summarize" | "refine";
streaming?: boolean; // Enable streaming responses
prompt_style?: "notebooklm" | "citation" | "conversational" | "neutral";
}export interface Notebook {
id: string;
user_id: string;
title: string;
settings: NotebookRAGSettings;
created_at: string;
updated_at: string;
source_count?: number; // Computed field for UI
}export interface CreateNotebookRequest {
title: string;
settings?: NotebookRAGSettings;
}
export interface UpdateNotebookRequest {
title?: string;
settings?: NotebookRAGSettings;
}export type DocumentStatus = "pending" | "processing" | "completed" | "failed";
export interface Document {
id: string;
notebook_id: string;
filename: string;
file_path: string;
mime_type: string;
status: DocumentStatus;
error_message: string | null;
chunk_count: number;
preview?: string | null; // First 500 chars for UI
created_at: string;
}
export interface UploadDocumentResponse {
status: string;
document_id: string;
notebook_id: string;
filename: string;
file_path: string;
mime_type: string;
processing_status: DocumentStatus;
chunk_count: number;
created_at: string;
}
export interface DocumentUrlResponse {
url: string;
expires_in: number; // Seconds until URL expires
}
export interface ProcessUrlRequest {
url: string;
notebook_id: string;
}
export interface ProcessUrlResponse {
status: string;
document_id: string;
processing_status: DocumentStatus;
}export interface Citation {
id: string;
message_id: string;
document_id: string;
filename?: string; // May be missing from older docs
text_preview: string;
score: number; // Relevance score (0-1)
page_number: number | null;
}
export interface ChatMessage {
id: string;
notebook_id: string;
role: "user" | "assistant";
content: string;
created_at: string;
citations: Citation[];
}
export interface SendMessageRequest {
message: string;
stream?: boolean;
}
export interface ChatResponse {
role: "assistant";
content: string;
citations: Citation[];
}export interface SuggestedQuestion {
id: string;
text: string;
context: string | null; // e.g., "Based on: document.pdf"
}
export interface SuggestionsResponse {
questions: SuggestedQuestion[];
generated_at: string;
document_count: number;
}
// Conversation-based suggestions
export interface ConversationSuggestionsRequest {
last_user_message: string;
last_assistant_message: string;
}
export interface ConversationSuggestionsResponse {
questions: string[];
}export type ContentType = "podcast" | "quiz" | "flashcard" | "mindmap" | "note";
export type ContentStatus = "pending" | "processing" | "completed" | "failed";export interface PodcastDialogueTurn {
speaker: "Host" | "Expert";
text: string;
}
export interface PodcastScript {
title: string;
introduction: string;
dialogue: PodcastDialogueTurn[];
conclusion: string;
}
export interface PodcastContent extends GeneratedContent {
content_type: "podcast";
content: PodcastScript;
audio_url: string | null;
}export interface QuizQuestion {
question: string;
options: string[];
correct_index: number;
explanation: string;
}
export interface Quiz {
title: string;
questions: QuizQuestion[];
}
export interface QuizContent extends GeneratedContent {
content_type: "quiz";
content: Quiz;
}export interface Flashcard {
front: string;
back: string;
}
export interface FlashcardDeck {
title: string;
cards: Flashcard[];
}
export interface FlashcardContent extends GeneratedContent {
content_type: "flashcard";
content: FlashcardDeck;
}export interface MindMapNode {
id: string;
label: string;
children?: MindMapNode[];
}
export interface MindMap {
title: string;
root: MindMapNode;
}
export interface MindMapContent extends GeneratedContent {
content_type: "mindmap";
content: MindMap;
}export interface GeneratedContent {
id: string;
notebook_id: string;
document_id: string | null;
content_type: ContentType;
status: ContentStatus;
content: PodcastScript | Quiz | FlashcardDeck | MindMap | NoteContent;
audio_url: string | null;
created_at: string;
updated_at: string;
}
export interface ContentListResponse {
items: GeneratedContent[];
total: number;
}
export interface GenerateContentRequest {
content_type: ContentType;
document_ids?: string[] | null;
}
export interface GenerateContentResponse {
id: string;
content_type: ContentType;
status: ContentStatus;
message: string;
}export interface Note {
id: string;
notebook_id: string;
title: string;
content: string; // HTML or Markdown
created_at: string;
updated_at: string;
}
export interface CreateNoteRequest {
notebookId: string;
title?: string;
content?: string;
}
export interface UpdateNoteRequest {
title?: string;
content?: string;
}
interface NoteContent {
title: string;
content: string;
}export interface TaskProgress {
id: string;
job_id: number;
user_id: string | null;
notebook_id: string | null;
document_id: string | null;
content_id: string | null;
progress_percent: number; // 0-100
message: string | null;
status: ContentStatus;
created_at: string;
updated_at: string;
}export type FeedbackContentType =
| "chat_response"
| "podcast"
| "quiz"
| "flashcard"
| "mindmap"
| "note";
export type FeedbackRating = "thumbs_up" | "thumbs_down";
export interface FeedbackRequest {
content_type: FeedbackContentType;
content_id: string;
rating: FeedbackRating;
comment?: string;
}
export interface FeedbackResponse {
id: string;
user_id: string;
content_type: FeedbackContentType;
content_id: string;
rating: FeedbackRating;
comment: string | null;
created_at: string;
}export interface HealthStatus {
status: "healthy" | "unhealthy";
timestamp: string;
}
export interface ServiceHealth {
status: "healthy" | "unhealthy";
message?: string;
}
export interface DetailedHealthStatus {
status: "healthy" | "unhealthy";
services: {
database: ServiceHealth;
qdrant: ServiceHealth;
storage: ServiceHealth;
};
timestamp: string;
}export interface ApiErrorResponse {
detail: string;
status?: number;
}
export interface RateLimitStatus {
limit: number;
remaining: number;
reset: number;
retryAfter?: number;
}
export interface ValidationError {
loc: (string | number)[];
msg: string;
type: string;
}
export interface ValidationErrorResponse {
detail: ValidationError[];
}interface Message {
id: string;
role: "user" | "assistant";
content: string;
timestamp: string;
citations?: Citation[];
isStreaming?: boolean;
}
interface LastChatTurn {
userMessage: string;
assistantMessage: string;
}
interface ChatPanelProps {
messages: Message[];
sourceCount: number;
notebookId: string | null;
onSendMessage: (content: string) => void;
onOpenSettings?: () => void;
onDeleteHistory?: () => void;
onViewSource?: (documentId: string, pageNumber?: number | null) => void;
lastChatTurn?: LastChatTurn | null;
onNoteSaved?: () => void;
}interface NotebookCardProps {
notebook: {
id: string;
title: string;
category: string;
date: string;
sources: number;
isPublic: boolean;
};
variant?: "featured" | "recent";
onUpdate?: (id: string, newTitle: string) => void;
}Helper functions for type narrowing:
// Check if content is a podcast
export function isPodcastContent(
content: GeneratedContent
): content is PodcastContent {
return content.content_type === "podcast";
}
// Check if content is a quiz
export function isQuizContent(
content: GeneratedContent
): content is QuizContent {
return content.content_type === "quiz";
}
// Check if content is flashcards
export function isFlashcardContent(
content: GeneratedContent
): content is FlashcardContent {
return content.content_type === "flashcard";
}
// Check if content is a mind map
export function isMindMapContent(
content: GeneratedContent
): content is MindMapContent {
return content.content_type === "mindmap";
}- Use Strict Types: Avoid
any, useunknownwhen type is truly unknown - Export Types: All types should be exported for reuse
- Document Fields: Add JSDoc comments for complex fields
- Use Unions: Use discriminated unions for variant types
- Null vs Undefined: Be explicit about optional vs nullable
- Readonly: Use
readonlyfor immutable data - Branded Types: Use for type-safe IDs
// Branded type example
type NotebookId = string & { __brand: "NotebookId" };
type DocumentId = string & { __brand: "DocumentId" };
function getNotebook(id: NotebookId): Notebook;
function getDocument(id: DocumentId): Document;
// Prevents mixing up IDs
const notebookId = "uuid" as NotebookId;
getDocument(notebookId); // Type error!