@msbayindir/context-rag 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +464 -0
- package/dist/bin/cli.cjs +210 -0
- package/dist/bin/cli.cjs.map +1 -0
- package/dist/bin/cli.d.cts +1 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +187 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/index.cjs +2877 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +812 -0
- package/dist/index.d.ts +812 -0
- package/dist/index.js +2842 -0
- package/dist/index.js.map +1 -0
- package/package.json +91 -0
- package/prisma/schema.prisma +225 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/config.types.ts","../src/errors/index.ts","../src/utils/logger.ts","../src/utils/hash.ts","../src/utils/retry.ts","../src/utils/rate-limiter.ts","../src/config/templates.ts","../src/types/enums.ts","../src/utils/chunk-parser.ts","../src/types/prompt.types.ts","../src/database/repositories/prompt-config.repository.ts","../src/database/repositories/document.repository.ts","../src/database/repositories/batch.repository.ts","../src/database/repositories/chunk.repository.ts","../src/database/utils.ts","../src/services/gemini.service.ts","../src/services/pdf.processor.ts","../src/enhancements/no-op.handler.ts","../src/types/rag-enhancement.types.ts","../src/enhancements/anthropic/anthropic.handler.ts","../src/enhancements/enhancement-registry.ts","../src/engines/ingestion.engine.ts","../src/engines/retrieval.engine.ts","../src/engines/discovery.engine.ts","../src/context-rag.ts"],"names":["z","createHash","GoogleGenerativeAI","GoogleAIFileManager","TaskType","fs","path","pdf","pLimit","result","sections"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\r\nimport type { RagEnhancementConfig } from './rag-enhancement.types.js';\r\n\r\n/**\r\n * Generic Prisma client type - allows any Prisma client instance\r\n * This avoids requiring the user to generate Prisma client before using the library\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type PrismaClientLike = any;\r\n\r\n/**\r\n * Batch processing configuration\r\n */\r\nexport interface BatchConfig {\r\n /** Number of pages per batch (default: 15) */\r\n pagesPerBatch: number;\r\n /** Maximum concurrent batch processing (default: 3) */\r\n maxConcurrency: number;\r\n /** Maximum retry attempts for failed batches (default: 3) */\r\n maxRetries: number;\r\n /** Initial retry delay in milliseconds (default: 1000) */\r\n retryDelayMs: number;\r\n /** Backoff multiplier for exponential retry (default: 2) */\r\n backoffMultiplier: number;\r\n}\r\n\r\n/**\r\n * Chunk configuration\r\n */\r\nexport interface ChunkConfig {\r\n /** Maximum tokens per chunk (default: 500) */\r\n maxTokens: number;\r\n /** Overlap tokens between chunks (default: 50) */\r\n overlapTokens: number;\r\n}\r\n\r\n/**\r\n * Rate limiting configuration\r\n */\r\nexport interface RateLimitConfig {\r\n /** Requests per minute limit (default: 60) */\r\n requestsPerMinute: number;\r\n /** Enable adaptive rate limiting (default: true) */\r\n adaptive: boolean;\r\n}\r\n\r\n/**\r\n * Logging configuration\r\n */\r\nexport interface LogConfig {\r\n /** Log level */\r\n level: 'debug' | 'info' | 'warn' | 'error';\r\n /** Enable structured JSON logging (default: true) */\r\n structured: boolean;\r\n /** Custom logger function */\r\n customLogger?: (level: string, message: string, meta?: Record<string, unknown>) => void;\r\n}\r\n\r\n/**\r\n * Generation configuration for Gemini API\r\n */\r\nexport interface GenerationConfig {\r\n /** Temperature for generation (0-2, default: 0.3) */\r\n temperature: number;\r\n /** Maximum output tokens (default: 8192) */\r\n maxOutputTokens: number;\r\n}\r\n\r\n/**\r\n * Main Context-RAG configuration\r\n */\r\nexport interface ContextRAGConfig {\r\n /** Prisma client instance */\r\n prisma: PrismaClientLike;\r\n /** Gemini API key */\r\n geminiApiKey: string;\r\n /** Gemini model to use (default: 'gemini-1.5-pro') */\r\n model?:\r\n | 'gemini-1.5-pro'\r\n | 'gemini-1.5-flash'\r\n | 'gemini-2.0-flash-exp'\r\n | 'gemini-pro'\r\n | 'gemini-2.5-pro'\r\n | 'gemini-3-pro-preview'\r\n | 'gemini-3-flash-preview';\r\n /** Embedding model (default: 'text-embedding-004') */\r\n embeddingModel?: string;\r\n /** Generation configuration (temperature, maxOutputTokens) */\r\n generationConfig?: Partial<GenerationConfig>;\r\n /** Batch processing configuration */\r\n batchConfig?: Partial<BatchConfig>;\r\n /** Chunk configuration */\r\n chunkConfig?: Partial<ChunkConfig>;\r\n /** Rate limiting configuration */\r\n rateLimitConfig?: Partial<RateLimitConfig>;\r\n /** Logging configuration */\r\n logging?: Partial<LogConfig>;\r\n /** RAG Enhancement configuration (Contextual Retrieval, etc.) */\r\n ragEnhancement?: RagEnhancementConfig;\r\n}\r\n\r\n/**\r\n * Internal resolved configuration with all defaults applied\r\n */\r\nexport interface ResolvedConfig {\r\n prisma: PrismaClientLike;\r\n geminiApiKey: string;\r\n model: string;\r\n embeddingModel: string;\r\n generationConfig: GenerationConfig;\r\n batchConfig: BatchConfig;\r\n chunkConfig: ChunkConfig;\r\n rateLimitConfig: RateLimitConfig;\r\n logging: LogConfig;\r\n ragEnhancement?: RagEnhancementConfig;\r\n}\r\n\r\n/**\r\n * Default configuration values\r\n */\r\nexport const DEFAULT_BATCH_CONFIG: BatchConfig = {\r\n pagesPerBatch: 15,\r\n maxConcurrency: 3,\r\n maxRetries: 3,\r\n retryDelayMs: 1000,\r\n backoffMultiplier: 2,\r\n};\r\n\r\nexport const DEFAULT_CHUNK_CONFIG: ChunkConfig = {\r\n maxTokens: 500,\r\n overlapTokens: 50,\r\n};\r\n\r\nexport const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig = {\r\n requestsPerMinute: 60,\r\n adaptive: true,\r\n};\r\n\r\nexport const DEFAULT_GENERATION_CONFIG: GenerationConfig = {\r\n temperature: 0.3,\r\n maxOutputTokens: 8192,\r\n};\r\n\r\nexport const DEFAULT_LOG_CONFIG: LogConfig = {\r\n level: 'info',\r\n structured: true,\r\n};\r\n\r\n/**\r\n * Zod schema for config validation\r\n */\r\nexport const configSchema = z.object({\r\n geminiApiKey: z.string().min(1, 'Gemini API key is required'),\r\n model: z.enum([\r\n 'gemini-1.5-pro',\r\n 'gemini-1.5-flash',\r\n 'gemini-2.0-flash-exp',\r\n 'gemini-pro',\r\n 'gemini-2.5-pro',\r\n 'gemini-3-pro-preview',\r\n 'gemini-3-flash-preview'\r\n ]).optional(),\r\n embeddingModel: z.string().optional(),\r\n batchConfig: z\r\n .object({\r\n pagesPerBatch: z.number().min(1).max(50).optional(),\r\n maxConcurrency: z.number().min(1).max(10).optional(),\r\n maxRetries: z.number().min(0).max(10).optional(),\r\n retryDelayMs: z.number().min(100).max(60000).optional(),\r\n backoffMultiplier: z.number().min(1).max(5).optional(),\r\n })\r\n .optional(),\r\n chunkConfig: z\r\n .object({\r\n maxTokens: z.number().min(100).max(2000).optional(),\r\n overlapTokens: z.number().min(0).max(500).optional(),\r\n })\r\n .optional(),\r\n rateLimitConfig: z\r\n .object({\r\n requestsPerMinute: z.number().min(1).max(1000).optional(),\r\n adaptive: z.boolean().optional(),\r\n })\r\n .optional(),\r\n logging: z\r\n .object({\r\n level: z.enum(['debug', 'info', 'warn', 'error']).optional(),\r\n structured: z.boolean().optional(),\r\n })\r\n .optional(),\r\n});\r\n\r\nexport type ContextRAGOptions = Omit<ContextRAGConfig, 'prisma'>;\r\n","/**\r\n * Base error class for Context-RAG\r\n */\r\nexport class ContextRAGError extends Error {\r\n public readonly code: string;\r\n public readonly details?: Record<string, unknown>;\r\n\r\n constructor(message: string, code: string, details?: Record<string, unknown>) {\r\n super(message);\r\n this.name = 'ContextRAGError';\r\n this.code = code;\r\n this.details = details;\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n\r\n toJSON(): Record<string, unknown> {\r\n return {\r\n name: this.name,\r\n code: this.code,\r\n message: this.message,\r\n details: this.details,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Configuration-related errors\r\n */\r\nexport class ConfigurationError extends ContextRAGError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, 'CONFIGURATION_ERROR', details);\r\n this.name = 'ConfigurationError';\r\n }\r\n}\r\n\r\n/**\r\n * Ingestion-related errors\r\n */\r\nexport class IngestionError extends ContextRAGError {\r\n public readonly batchIndex?: number;\r\n public readonly retryable: boolean;\r\n\r\n constructor(\r\n message: string,\r\n options: {\r\n batchIndex?: number;\r\n retryable?: boolean;\r\n details?: Record<string, unknown>;\r\n } = {}\r\n ) {\r\n super(message, 'INGESTION_ERROR', options.details);\r\n this.name = 'IngestionError';\r\n this.batchIndex = options.batchIndex;\r\n this.retryable = options.retryable ?? false;\r\n }\r\n}\r\n\r\n/**\r\n * Search-related errors\r\n */\r\nexport class SearchError extends ContextRAGError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, 'SEARCH_ERROR', details);\r\n this.name = 'SearchError';\r\n }\r\n}\r\n\r\n/**\r\n * Discovery-related errors\r\n */\r\nexport class DiscoveryError extends ContextRAGError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, 'DISCOVERY_ERROR', details);\r\n this.name = 'DiscoveryError';\r\n }\r\n}\r\n\r\n/**\r\n * Database-related errors\r\n */\r\nexport class DatabaseError extends ContextRAGError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, 'DATABASE_ERROR', details);\r\n this.name = 'DatabaseError';\r\n }\r\n}\r\n\r\n/**\r\n * Rate limit errors (retryable)\r\n */\r\nexport class RateLimitError extends ContextRAGError {\r\n public readonly retryAfterMs?: number;\r\n\r\n constructor(message: string, retryAfterMs?: number) {\r\n super(message, 'RATE_LIMIT_ERROR', { retryAfterMs });\r\n this.name = 'RateLimitError';\r\n this.retryAfterMs = retryAfterMs;\r\n }\r\n}\r\n\r\n/**\r\n * Validation errors\r\n */\r\nexport class ValidationError extends ContextRAGError {\r\n public readonly field?: string;\r\n\r\n constructor(message: string, field?: string, details?: Record<string, unknown>) {\r\n super(message, 'VALIDATION_ERROR', { field, ...details });\r\n this.name = 'ValidationError';\r\n this.field = field;\r\n }\r\n}\r\n\r\n/**\r\n * Not found errors\r\n */\r\nexport class NotFoundError extends ContextRAGError {\r\n public readonly resourceType: string;\r\n public readonly resourceId: string;\r\n\r\n constructor(resourceType: string, resourceId: string) {\r\n super(`${resourceType} not found: ${resourceId}`, 'NOT_FOUND', {\r\n resourceType,\r\n resourceId,\r\n });\r\n this.name = 'NotFoundError';\r\n this.resourceType = resourceType;\r\n this.resourceId = resourceId;\r\n }\r\n}\r\n","import type { LogConfig } from '../types/config.types.js';\r\n\r\nexport interface LogMeta {\r\n correlationId?: string;\r\n documentId?: string;\r\n batchId?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface Logger {\r\n debug(message: string, meta?: LogMeta): void;\r\n info(message: string, meta?: LogMeta): void;\r\n warn(message: string, meta?: LogMeta): void;\r\n error(message: string, meta?: LogMeta): void;\r\n}\r\n\r\nconst LOG_LEVELS = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n} as const;\r\n\r\n/**\r\n * Creates a logger instance based on configuration\r\n */\r\nexport function createLogger(config: LogConfig): Logger {\r\n const currentLevel = LOG_LEVELS[config.level];\r\n\r\n const shouldLog = (level: keyof typeof LOG_LEVELS): boolean => {\r\n return LOG_LEVELS[level] >= currentLevel;\r\n };\r\n\r\n const formatMessage = (\r\n level: string,\r\n message: string,\r\n meta?: LogMeta\r\n ): string => {\r\n if (config.structured) {\r\n return JSON.stringify({\r\n timestamp: new Date().toISOString(),\r\n level,\r\n message,\r\n ...meta,\r\n });\r\n }\r\n const metaStr = meta ? ` ${JSON.stringify(meta)}` : '';\r\n return `[${new Date().toISOString()}] [${level.toUpperCase()}] ${message}${metaStr}`;\r\n };\r\n\r\n const log = (level: keyof typeof LOG_LEVELS, message: string, meta?: LogMeta): void => {\r\n if (!shouldLog(level)) return;\r\n\r\n if (config.customLogger) {\r\n config.customLogger(level, message, meta);\r\n return;\r\n }\r\n\r\n const formattedMessage = formatMessage(level, message, meta);\r\n\r\n switch (level) {\r\n case 'debug':\r\n case 'info':\r\n // eslint-disable-next-line no-console\r\n console.log(formattedMessage);\r\n break;\r\n case 'warn':\r\n console.warn(formattedMessage);\r\n break;\r\n case 'error':\r\n console.error(formattedMessage);\r\n break;\r\n }\r\n };\r\n\r\n return {\r\n debug: (message: string, meta?: LogMeta) => log('debug', message, meta),\r\n info: (message: string, meta?: LogMeta) => log('info', message, meta),\r\n warn: (message: string, meta?: LogMeta) => log('warn', message, meta),\r\n error: (message: string, meta?: LogMeta) => log('error', message, meta),\r\n };\r\n}\r\n\r\n/**\r\n * Generate a unique correlation ID for tracking operations\r\n */\r\nexport function generateCorrelationId(): string {\r\n return `crag_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\r\n}\r\n","import { createHash } from 'crypto';\r\nimport * as fs from 'fs/promises';\r\n\r\n/**\r\n * Calculate SHA-256 hash of a buffer\r\n */\r\nexport function hashBuffer(buffer: Buffer): string {\r\n return createHash('sha256').update(buffer).digest('hex');\r\n}\r\n\r\n/**\r\n * Calculate SHA-256 hash of a file\r\n */\r\nexport async function hashFile(filePath: string): Promise<string> {\r\n const buffer = await fs.readFile(filePath);\r\n return hashBuffer(buffer);\r\n}\r\n\r\n/**\r\n * Generate a short hash for display purposes\r\n */\r\nexport function shortHash(hash: string, length: number = 8): string {\r\n return hash.substring(0, length);\r\n}\r\n","import type { BatchConfig } from '../types/config.types.js';\r\nimport { RateLimitError } from '../errors/index.js';\r\n\r\nexport interface RetryOptions {\r\n maxRetries: number;\r\n initialDelayMs: number;\r\n maxDelayMs: number;\r\n backoffMultiplier: number;\r\n retryableErrors?: string[];\r\n onRetry?: (attempt: number, error: Error, delayMs: number) => void;\r\n}\r\n\r\n/**\r\n * Default retry options from batch config\r\n */\r\nexport function getRetryOptions(batchConfig: BatchConfig): RetryOptions {\r\n return {\r\n maxRetries: batchConfig.maxRetries,\r\n initialDelayMs: batchConfig.retryDelayMs,\r\n maxDelayMs: 30000,\r\n backoffMultiplier: batchConfig.backoffMultiplier,\r\n retryableErrors: ['429', '503', 'TIMEOUT', 'ECONNRESET', 'ETIMEDOUT'],\r\n };\r\n}\r\n\r\n/**\r\n * Check if an error is retryable\r\n */\r\nexport function isRetryableError(error: Error, retryableErrors: string[] = []): boolean {\r\n const errorString = error.message + (error.name || '');\r\n\r\n // Rate limit errors are always retryable\r\n if (error instanceof RateLimitError) {\r\n return true;\r\n }\r\n\r\n // Check against retryable error patterns\r\n return retryableErrors.some(pattern =>\r\n errorString.includes(pattern) || error.name.includes(pattern)\r\n );\r\n}\r\n\r\n/**\r\n * Calculate delay with exponential backoff\r\n */\r\nexport function calculateBackoffDelay(\r\n attempt: number,\r\n initialDelayMs: number,\r\n backoffMultiplier: number,\r\n maxDelayMs: number\r\n): number {\r\n const delay = initialDelayMs * Math.pow(backoffMultiplier, attempt - 1);\r\n // Add jitter (±10%)\r\n const jitter = delay * 0.1 * (Math.random() * 2 - 1);\r\n return Math.min(delay + jitter, maxDelayMs);\r\n}\r\n\r\n/**\r\n * Sleep for a specified duration\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Execute a function with retry logic\r\n */\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n options: RetryOptions\r\n): Promise<T> {\r\n let lastError: Error | undefined;\r\n\r\n for (let attempt = 1; attempt <= options.maxRetries + 1; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error as Error;\r\n\r\n // Check if we should retry\r\n if (attempt > options.maxRetries) {\r\n break;\r\n }\r\n\r\n if (!isRetryableError(lastError, options.retryableErrors)) {\r\n throw lastError;\r\n }\r\n\r\n // Calculate delay\r\n let delayMs = calculateBackoffDelay(\r\n attempt,\r\n options.initialDelayMs,\r\n options.backoffMultiplier,\r\n options.maxDelayMs\r\n );\r\n\r\n // Use retry-after header if available\r\n if (lastError instanceof RateLimitError && lastError.retryAfterMs) {\r\n delayMs = Math.max(delayMs, lastError.retryAfterMs);\r\n }\r\n\r\n // Notify about retry\r\n options.onRetry?.(attempt, lastError, delayMs);\r\n\r\n // Wait before retrying\r\n await sleep(delayMs);\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n","import type { RateLimitConfig } from '../types/config.types.js';\r\nimport { sleep } from './retry.js';\r\n\r\ninterface RateLimitState {\r\n tokens: number;\r\n lastRefill: number;\r\n currentRpm: number;\r\n consecutiveSuccesses: number;\r\n consecutiveFailures: number;\r\n}\r\n\r\n/**\r\n * Token bucket rate limiter with adaptive capabilities\r\n */\r\nexport class RateLimiter {\r\n private readonly config: RateLimitConfig;\r\n private state: RateLimitState;\r\n private readonly minRpm: number;\r\n private readonly maxRpm: number;\r\n private readonly intervalMs: number = 60000; // 1 minute\r\n\r\n constructor(config: RateLimitConfig) {\r\n this.config = config;\r\n this.minRpm = Math.floor(config.requestsPerMinute * 0.2);\r\n this.maxRpm = Math.floor(config.requestsPerMinute * 1.5);\r\n\r\n this.state = {\r\n tokens: config.requestsPerMinute,\r\n lastRefill: Date.now(),\r\n currentRpm: config.requestsPerMinute,\r\n consecutiveSuccesses: 0,\r\n consecutiveFailures: 0,\r\n };\r\n }\r\n\r\n /**\r\n * Wait until a token is available and consume it\r\n */\r\n async acquire(): Promise<void> {\r\n this.refillTokens();\r\n\r\n while (this.state.tokens < 1) {\r\n const waitTime = this.calculateWaitTime();\r\n await sleep(waitTime);\r\n this.refillTokens();\r\n }\r\n\r\n this.state.tokens -= 1;\r\n }\r\n\r\n /**\r\n * Report a successful request (for adaptive rate limiting)\r\n */\r\n reportSuccess(): void {\r\n if (!this.config.adaptive) return;\r\n\r\n this.state.consecutiveSuccesses += 1;\r\n this.state.consecutiveFailures = 0;\r\n\r\n // Increase rate after 10 consecutive successes\r\n if (this.state.consecutiveSuccesses >= 10) {\r\n this.adjustRate(1.1); // +10%\r\n this.state.consecutiveSuccesses = 0;\r\n }\r\n }\r\n\r\n /**\r\n * Report a rate limit error (for adaptive rate limiting)\r\n */\r\n reportRateLimitError(): void {\r\n if (!this.config.adaptive) return;\r\n\r\n this.state.consecutiveFailures += 1;\r\n this.state.consecutiveSuccesses = 0;\r\n\r\n // Decrease rate immediately on rate limit\r\n this.adjustRate(0.7); // -30%\r\n }\r\n\r\n /**\r\n * Get current rate limit status\r\n */\r\n getStatus(): { currentRpm: number; availableTokens: number } {\r\n this.refillTokens();\r\n return {\r\n currentRpm: this.state.currentRpm,\r\n availableTokens: Math.floor(this.state.tokens),\r\n };\r\n }\r\n\r\n private refillTokens(): void {\r\n const now = Date.now();\r\n const elapsed = now - this.state.lastRefill;\r\n const tokensToAdd = (elapsed / this.intervalMs) * this.state.currentRpm;\r\n\r\n this.state.tokens = Math.min(\r\n this.state.tokens + tokensToAdd,\r\n this.state.currentRpm\r\n );\r\n this.state.lastRefill = now;\r\n }\r\n\r\n private calculateWaitTime(): number {\r\n const tokensNeeded = 1 - this.state.tokens;\r\n return Math.ceil((tokensNeeded / this.state.currentRpm) * this.intervalMs);\r\n }\r\n\r\n private adjustRate(multiplier: number): void {\r\n const newRpm = Math.floor(this.state.currentRpm * multiplier);\r\n this.state.currentRpm = Math.max(this.minRpm, Math.min(newRpm, this.maxRpm));\r\n }\r\n}\r\n","/**\r\n * Context-RAG Template Configuration\r\n * \r\n * This file contains all prompt templates used for document processing.\r\n * Templates use {{PLACEHOLDER}} syntax for dynamic content injection.\r\n */\r\n\r\n// ============================================\r\n// DISCOVERY TEMPLATE\r\n// ============================================\r\n\r\n/**\r\n * Template for document analysis and strategy discovery.\r\n * AI returns structured JSON with document-specific instructions.\r\n */\r\nexport const DISCOVERY_TEMPLATE = `You are a document analysis AI. Analyze the provided document and determine the optimal processing strategy.\r\n\r\nAnalyze the document and return ONLY a JSON response with the following structure:\r\n\r\n{\r\n \"documentType\": \"Medical|Legal|Financial|Technical|Academic|General\",\r\n \"documentTypeName\": \"Human readable name for this document type\",\r\n \"language\": \"tr|en|de|fr|...\",\r\n \"complexity\": \"low|medium|high\",\r\n \r\n \"detectedElements\": [\r\n { \"type\": \"table\", \"count\": 5, \"description\": \"Brief description of tables\" },\r\n { \"type\": \"list\", \"count\": 10, \"description\": \"Brief description of lists\" },\r\n { \"type\": \"code\", \"count\": 0, \"description\": \"\" },\r\n { \"type\": \"image\", \"count\": 3, \"description\": \"Brief description of images\" }\r\n ],\r\n \r\n \"specialInstructions\": [\r\n \"Specific instruction 1 for this document type\",\r\n \"Specific instruction 2 for this document type\",\r\n \"Specific instruction 3 for this document type\"\r\n ],\r\n \r\n \"exampleFormats\": {\r\n \"example1\": \"How a specific format should look\",\r\n \"example2\": \"Another format example\"\r\n },\r\n \r\n \"chunkStrategy\": {\r\n \"maxTokens\": 800,\r\n \"overlapTokens\": 100,\r\n \"splitBy\": \"section|page|paragraph|semantic\",\r\n \"preserveTables\": true,\r\n \"preserveLists\": true\r\n },\r\n \r\n \"confidence\": 0.85,\r\n \"reasoning\": \"Brief explanation of why this strategy was chosen\"\r\n}\r\n\r\nIMPORTANT RULES:\r\n1. DO NOT generate a full extraction prompt\r\n2. Only provide structured analysis and specific instructions\r\n3. Instructions should be actionable and specific to this document type\r\n4. Example formats help maintain consistency in extraction\r\n\r\n{{DOCUMENT_TYPE_HINT}}\r\n`;\r\n\r\n// ============================================\r\n// BASE EXTRACTION TEMPLATE\r\n// ============================================\r\n\r\n/**\r\n * Base template for content extraction.\r\n * Document-specific instructions are injected via {{DOCUMENT_INSTRUCTIONS}}.\r\n */\r\nexport const BASE_EXTRACTION_TEMPLATE = `You are a document processing AI. Extract content following the EXACT format below.\r\n\r\n## OUTPUT FORMAT (MANDATORY - DO NOT MODIFY)\r\n\r\nUse this structure for EVERY content section:\r\n\r\n<!-- SECTION type=\"[TYPE]\" page=\"[PAGE]\" confidence=\"[0.0-1.0]\" -->\r\n[Content here in Markdown format]\r\n<!-- /SECTION -->\r\n\r\n### Valid Types:\r\n- TEXT: Regular paragraphs and prose\r\n- TABLE: Data tables in Markdown format\r\n- LIST: Bullet (-) or numbered (1. 2. 3.) lists\r\n- HEADING: Section headers with # ## ### levels\r\n- CODE: Code blocks with language specification\r\n- QUOTE: Quoted text or citations\r\n- IMAGE_REF: Description of images, charts, figures\r\n- QUESTION: Multiple choice questions with options (A, B, C, D, E)\r\n\r\n### Format Rules:\r\n1. **Tables**: Use Markdown table format\r\n | Column1 | Column2 | Column3 |\r\n |---------|---------|---------|\r\n | data | data | data |\r\n\r\n2. **Lists**: Use consistent format\r\n - Bullet item\r\n - Another bullet\r\n \r\n OR\r\n \r\n 1. Numbered item\r\n 2. Another numbered\r\n\r\n3. **Headings**: Maximum 3 levels, use hierarchy\r\n # Main Section\r\n ## Subsection\r\n ### Sub-subsection\r\n\r\n4. **Code**: Specify language\r\n \\`\\`\\`python\r\n code here\r\n \\`\\`\\`\r\n\r\n5. **Images**: Describe visual content\r\n [IMAGE: Description of what the image shows]\r\n\r\n6. **Questions**: Multiple choice questions with options\r\n **Question 1:** Question text here?\r\n A) Option A text\r\n B) Option B text\r\n C) Option C text\r\n D) Option D text\r\n E) Option E text (if exists)\r\n **Answer:** [Letter] (if answer is provided in document)\r\n\r\n## DOCUMENT-SPECIFIC INSTRUCTIONS\r\n{{DOCUMENT_INSTRUCTIONS}}\r\n\r\n## CRITICAL EXTRACTION RULES (DO NOT VIOLATE)\r\n⚠️ These rules are MANDATORY for legal, medical, and financial document accuracy:\r\n\r\n1. **NO SUMMARIZATION**: Extract content EXACTLY as written. Do not summarize, paraphrase, or condense.\r\n2. **NO INTERPRETATION**: Do not interpret, explain, or add commentary to the content.\r\n3. **PRESERVE ORIGINAL WORDING**: Keep exact terminology, especially for:\r\n - Legal terms, clauses, and article references\r\n - Medical terminology, diagnoses, and prescriptions\r\n - Financial figures, percentages, and calculations\r\n - Technical specifications and measurements\r\n4. **VERBATIM EXTRACTION**: Copy text word-for-word from the document.\r\n5. **NO OMISSIONS**: Include all content, even if it seems redundant or repetitive.\r\n6. **UNCLEAR CONTENT**: If text is unclear or illegible, extract as-is and mark: [UNCLEAR: partial text visible]\r\n7. **FOREIGN TERMS**: Keep foreign language terms, Latin phrases, and abbreviations exactly as written.\r\n\r\n## PROCESSING RULES\r\n- Extract ALL content completely, do not summarize or skip\r\n- Preserve original document structure and hierarchy\r\n- Include page references for each section\r\n- Maintain technical accuracy and terminology\r\n- Use appropriate confidence scores based on extraction quality\r\n- If content spans multiple pages, use the starting page number\r\n\r\n## PAGE RANGE\r\n{{PAGE_RANGE}}\r\n`;\r\n\r\n// ============================================\r\n// DEFAULT DOCUMENT INSTRUCTIONS\r\n// ============================================\r\n\r\n/**\r\n * Default instructions when no Discovery result is available\r\n */\r\nexport const DEFAULT_DOCUMENT_INSTRUCTIONS = `\r\n- Extract all text content preserving structure\r\n- Convert tables to Markdown table format\r\n- Convert lists to Markdown list format\r\n- Preserve headings with appropriate # levels\r\n- Note any images with descriptive text\r\n- Maintain the logical flow of content\r\n`;\r\n\r\n// ============================================\r\n// TEMPLATE BUILDER FUNCTIONS\r\n// ============================================\r\n\r\n/**\r\n * Build extraction prompt from discovery result\r\n */\r\nexport function buildExtractionPrompt(\r\n documentInstructions: string[],\r\n exampleFormats?: Record<string, string>,\r\n pageStart?: number,\r\n pageEnd?: number\r\n): string {\r\n // Build instructions section\r\n let instructionsBlock = documentInstructions\r\n .map(instruction => `- ${instruction}`)\r\n .join('\\n');\r\n\r\n // Add example formats if provided\r\n if (exampleFormats && Object.keys(exampleFormats).length > 0) {\r\n instructionsBlock += '\\n\\n### Example Formats:\\n';\r\n for (const [key, value] of Object.entries(exampleFormats)) {\r\n instructionsBlock += `- **${key}**: \\`${value}\\`\\n`;\r\n }\r\n }\r\n\r\n // Build page range description\r\n let pageRange = '';\r\n if (pageStart !== undefined && pageEnd !== undefined) {\r\n if (pageStart === pageEnd) {\r\n pageRange = `Process page ${pageStart} of this document.`;\r\n } else {\r\n pageRange = `Process pages ${pageStart}-${pageEnd} of this document.`;\r\n }\r\n }\r\n\r\n return BASE_EXTRACTION_TEMPLATE\r\n .replace('{{DOCUMENT_INSTRUCTIONS}}', instructionsBlock || DEFAULT_DOCUMENT_INSTRUCTIONS)\r\n .replace('{{PAGE_RANGE}}', pageRange);\r\n}\r\n\r\n/**\r\n * Build discovery prompt with optional type hint\r\n */\r\nexport function buildDiscoveryPrompt(documentTypeHint?: string): string {\r\n let hint = '';\r\n if (documentTypeHint) {\r\n hint = `\\nHint: The user expects this to be a \"${documentTypeHint}\" document. Consider this when analyzing.`;\r\n }\r\n\r\n return DISCOVERY_TEMPLATE.replace('{{DOCUMENT_TYPE_HINT}}', hint);\r\n}\r\n\r\n// ============================================\r\n// SECTION REGEX PATTERNS\r\n// ============================================\r\n\r\n/**\r\n * Regex pattern to match SECTION blocks in AI output\r\n */\r\nexport const SECTION_PATTERN = /<!-- SECTION type=\"(\\w+)\" page=\"(\\d+)\" confidence=\"([\\d.]+)\" -->\\n?([\\s\\S]*?)\\n?<!-- \\/SECTION -->/g;\r\n\r\n/**\r\n * Regex pattern for single SECTION match\r\n */\r\nexport const SECTION_PATTERN_SINGLE = /<!-- SECTION type=\"(\\w+)\" page=\"(\\d+)\" confidence=\"([\\d.]+)\" -->\\n?([\\s\\S]*?)\\n?<!-- \\/SECTION -->/;\r\n","/**\r\n * Chunk type enumeration\r\n * Defines the type of content within a chunk\r\n */\r\nexport const ChunkTypeEnum = {\r\n TEXT: 'TEXT',\r\n TABLE: 'TABLE',\r\n LIST: 'LIST',\r\n CODE: 'CODE',\r\n HEADING: 'HEADING',\r\n IMAGE_REF: 'IMAGE_REF',\r\n QUOTE: 'QUOTE',\r\n QUESTION: 'QUESTION',\r\n MIXED: 'MIXED',\r\n} as const;\r\n\r\nexport type ChunkTypeEnumType = (typeof ChunkTypeEnum)[keyof typeof ChunkTypeEnum];\r\n\r\n/**\r\n * Batch processing status enumeration\r\n */\r\nexport const BatchStatusEnum = {\r\n PENDING: 'PENDING',\r\n PROCESSING: 'PROCESSING',\r\n RETRYING: 'RETRYING',\r\n COMPLETED: 'COMPLETED',\r\n FAILED: 'FAILED',\r\n} as const;\r\n\r\nexport type BatchStatusEnumType = (typeof BatchStatusEnum)[keyof typeof BatchStatusEnum];\r\n\r\n/**\r\n * Document processing status enumeration\r\n */\r\nexport const DocumentStatusEnum = {\r\n PENDING: 'PENDING',\r\n DISCOVERING: 'DISCOVERING',\r\n AWAITING_APPROVAL: 'AWAITING_APPROVAL',\r\n PROCESSING: 'PROCESSING',\r\n COMPLETED: 'COMPLETED',\r\n FAILED: 'FAILED',\r\n PARTIAL: 'PARTIAL',\r\n} as const;\r\n\r\nexport type DocumentStatusEnumType = (typeof DocumentStatusEnum)[keyof typeof DocumentStatusEnum];\r\n\r\n/**\r\n * Confidence level enumeration\r\n */\r\nexport const ConfidenceLevelEnum = {\r\n HIGH: 'HIGH',\r\n MEDIUM: 'MEDIUM',\r\n LOW: 'LOW',\r\n} as const;\r\n\r\nexport type ConfidenceLevelEnumType = (typeof ConfidenceLevelEnum)[keyof typeof ConfidenceLevelEnum];\r\n\r\n/**\r\n * Search mode enumeration\r\n */\r\nexport const SearchModeEnum = {\r\n SEMANTIC: 'semantic',\r\n KEYWORD: 'keyword',\r\n HYBRID: 'hybrid',\r\n} as const;\r\n\r\nexport type SearchModeEnumType = (typeof SearchModeEnum)[keyof typeof SearchModeEnum];\r\n","/**\r\n * Chunk Parser Utility\r\n * \r\n * Parse AI-generated content with SECTION markers into structured chunks.\r\n */\r\n\r\nimport { SECTION_PATTERN } from '../config/templates.js';\r\nimport { ChunkTypeEnum, type ChunkTypeEnumType } from '../types/enums.js';\r\n\r\n/**\r\n * Parsed section from AI output\r\n */\r\nexport interface ParsedSection {\r\n /** Content type: TEXT, TABLE, LIST, etc. */\r\n type: ChunkTypeEnumType;\r\n /** Source page number */\r\n page: number;\r\n /** AI confidence score (0.0 - 1.0) */\r\n confidence: number;\r\n /** Raw content in Markdown format */\r\n content: string;\r\n /** Original index in the document */\r\n index: number;\r\n}\r\n\r\n/**\r\n * Parse AI output containing SECTION markers into structured sections\r\n * \r\n * @param aiOutput - Raw AI output with <!-- SECTION --> markers\r\n * @returns Array of parsed sections\r\n * \r\n * @example\r\n * ```typescript\r\n * const output = `\r\n * <!-- SECTION type=\"TEXT\" page=\"1\" confidence=\"0.95\" -->\r\n * Some content here\r\n * <!-- /SECTION -->\r\n * `;\r\n * const sections = parseSections(output);\r\n * // [{ type: 'TEXT', page: 1, confidence: 0.95, content: 'Some content here', index: 0 }]\r\n * ```\r\n */\r\nexport function parseSections(aiOutput: string): ParsedSection[] {\r\n const sections: ParsedSection[] = [];\r\n\r\n // Reset regex state\r\n const regex = new RegExp(SECTION_PATTERN.source, 'g');\r\n let match: RegExpExecArray | null;\r\n let index = 0;\r\n\r\n while ((match = regex.exec(aiOutput)) !== null) {\r\n const typeStr = (match[1] ?? 'TEXT').toUpperCase();\r\n const page = parseInt(match[2] ?? '1', 10);\r\n const confidence = parseFloat(match[3] ?? '0.5');\r\n const content = (match[4] ?? '').trim();\r\n\r\n // Validate and map type\r\n const type = mapToChunkType(typeStr);\r\n\r\n sections.push({\r\n type,\r\n page,\r\n confidence: isNaN(confidence) ? 0.5 : Math.min(1, Math.max(0, confidence)),\r\n content,\r\n index: index++,\r\n });\r\n }\r\n\r\n return sections;\r\n}\r\n\r\n/**\r\n * Map string type to ChunkTypeEnum\r\n */\r\nfunction mapToChunkType(typeStr: string): ChunkTypeEnumType {\r\n const typeMap: Record<string, ChunkTypeEnumType> = {\r\n 'TEXT': ChunkTypeEnum.TEXT,\r\n 'TABLE': ChunkTypeEnum.TABLE,\r\n 'LIST': ChunkTypeEnum.LIST,\r\n 'CODE': ChunkTypeEnum.CODE,\r\n 'HEADING': ChunkTypeEnum.HEADING,\r\n 'QUOTE': ChunkTypeEnum.QUOTE,\r\n 'IMAGE_REF': ChunkTypeEnum.IMAGE_REF,\r\n 'QUESTION': ChunkTypeEnum.QUESTION,\r\n 'MIXED': ChunkTypeEnum.MIXED,\r\n };\r\n\r\n return typeMap[typeStr] ?? ChunkTypeEnum.TEXT;\r\n}\r\n\r\n/**\r\n * Check if AI output contains valid SECTION markers\r\n * \r\n * @param aiOutput - Raw AI output to check\r\n * @returns true if at least one valid SECTION found\r\n */\r\nexport function hasValidSections(aiOutput: string): boolean {\r\n const regex = new RegExp(SECTION_PATTERN.source);\r\n return regex.test(aiOutput);\r\n}\r\n\r\n/**\r\n * Fallback parser for content without SECTION markers\r\n * Splits content by double newlines and headers\r\n * \r\n * @param content - Raw content without markers\r\n * @param pageStart - Starting page number\r\n * @param pageEnd - Ending page number\r\n * @returns Array of parsed sections with inferred types\r\n */\r\nexport function parseFallbackContent(\r\n content: string,\r\n pageStart: number,\r\n _pageEnd: number\r\n): ParsedSection[] {\r\n const sections: ParsedSection[] = [];\r\n\r\n // Split by double newlines or headers\r\n const parts = content.split(/\\n(?=#{1,6}\\s)|(?:\\n\\n)/);\r\n\r\n let index = 0;\r\n for (const part of parts) {\r\n const trimmed = part.trim();\r\n if (!trimmed || trimmed.length < 10) continue;\r\n\r\n sections.push({\r\n type: detectContentType(trimmed),\r\n page: pageStart,\r\n confidence: 0.6, // Lower confidence for fallback\r\n content: trimmed,\r\n index: index++,\r\n });\r\n }\r\n\r\n return sections;\r\n}\r\n\r\n/**\r\n * Detect content type from text patterns\r\n */\r\nfunction detectContentType(content: string): ChunkTypeEnumType {\r\n // Table detection: has | and ---\r\n if (content.includes('|') && content.includes('---')) {\r\n return ChunkTypeEnum.TABLE;\r\n }\r\n\r\n // List detection: starts with - or number\r\n if (/^[-*]\\s/m.test(content) || /^\\d+\\.\\s/m.test(content)) {\r\n return ChunkTypeEnum.LIST;\r\n }\r\n\r\n // Code detection: starts with ```\r\n if (content.includes('```')) {\r\n return ChunkTypeEnum.CODE;\r\n }\r\n\r\n // Heading detection: starts with #\r\n if (/^#{1,6}\\s/.test(content)) {\r\n return ChunkTypeEnum.HEADING;\r\n }\r\n\r\n // Quote detection: starts with >\r\n if (content.startsWith('>')) {\r\n return ChunkTypeEnum.QUOTE;\r\n }\r\n\r\n // Image reference detection\r\n if (content.includes('[IMAGE:')) {\r\n return ChunkTypeEnum.IMAGE_REF;\r\n }\r\n\r\n // Question detection: A) B) C) D) or A. B. C. D. pattern\r\n if (/[A-E][).]\\s/m.test(content) && /[B-E][).]\\s/m.test(content)) {\r\n return ChunkTypeEnum.QUESTION;\r\n }\r\n\r\n return ChunkTypeEnum.TEXT;\r\n}\r\n\r\n/**\r\n * Clean content for search (remove Markdown formatting)\r\n * \r\n * @param content - Markdown formatted content\r\n * @returns Plain text suitable for vector search\r\n */\r\nexport function cleanForSearch(content: string): string {\r\n return content\r\n .replace(/#{1,6}\\s/g, '') // Remove heading markers\r\n .replace(/\\*\\*/g, '') // Remove bold\r\n .replace(/\\*/g, '') // Remove italic\r\n .replace(/`/g, '') // Remove code markers\r\n .replace(/\\|/g, ' ') // Replace table pipes with spaces\r\n .replace(/---+/g, '') // Remove horizontal rules\r\n .replace(/\\[IMAGE:[^\\]]*\\]/g, '') // Remove image refs\r\n .replace(/<!--.*?-->/gs, '') // Remove HTML comments\r\n .replace(/\\s+/g, ' ') // Normalize whitespace\r\n .trim();\r\n}\r\n\r\n/**\r\n * Extract search and display content from a section\r\n */\r\nexport interface ProcessedChunk {\r\n searchContent: string;\r\n displayContent: string;\r\n type: ChunkTypeEnumType;\r\n page: number;\r\n confidence: number;\r\n}\r\n\r\n/**\r\n * Process a parsed section into search and display formats\r\n */\r\nexport function processSection(section: ParsedSection): ProcessedChunk {\r\n return {\r\n searchContent: cleanForSearch(section.content),\r\n displayContent: section.content,\r\n type: section.type,\r\n page: section.page,\r\n confidence: section.confidence,\r\n };\r\n}\r\n","import type { ChunkStrategy } from './chunk.types.js';\r\n\r\n/**\r\n * Prompt configuration stored in database\r\n */\r\nexport interface PromptConfig {\r\n id: string;\r\n /** Document type identifier (e.g., 'Medical', 'Legal') */\r\n documentType: string;\r\n /** Human-readable name */\r\n name: string;\r\n /** System prompt for AI processing */\r\n systemPrompt: string;\r\n /** Chunking strategy configuration */\r\n chunkStrategy: ChunkStrategy;\r\n /** Version number for this document type */\r\n version: number;\r\n /** Whether this config is active */\r\n isActive: boolean;\r\n /** Whether this is the default for the document type */\r\n isDefault: boolean;\r\n /** Who created this config: 'discovery' | 'manual' | user ID */\r\n createdBy?: string;\r\n /** Change log / reason for this version */\r\n changeLog?: string;\r\n createdAt: Date;\r\n updatedAt: Date;\r\n}\r\n\r\n/**\r\n * Input for creating a new prompt config\r\n */\r\nexport interface CreatePromptConfig {\r\n /** Document type identifier */\r\n documentType: string;\r\n /** Human-readable name */\r\n name: string;\r\n /** System prompt for AI processing */\r\n systemPrompt: string;\r\n /** Optional chunk strategy (defaults applied if not provided) */\r\n chunkStrategy?: Partial<ChunkStrategy>;\r\n /** Set as default for this document type */\r\n setAsDefault?: boolean;\r\n /** Change log / reason */\r\n changeLog?: string;\r\n}\r\n\r\n/**\r\n * Input for updating a prompt config\r\n */\r\nexport interface UpdatePromptConfig {\r\n /** New system prompt */\r\n systemPrompt?: string;\r\n /** New chunk strategy */\r\n chunkStrategy?: Partial<ChunkStrategy>;\r\n /** New name */\r\n name?: string;\r\n /** Change log / reason for update */\r\n changeLog?: string;\r\n}\r\n\r\n/**\r\n * Prompt config query filters\r\n */\r\nexport interface PromptConfigFilters {\r\n /** Filter by document type */\r\n documentType?: string;\r\n /** Only active configs */\r\n activeOnly?: boolean;\r\n /** Only default configs */\r\n defaultOnly?: boolean;\r\n /** Created by filter */\r\n createdBy?: string;\r\n}\r\n\r\n/**\r\n * Default chunk strategy\r\n */\r\nexport const DEFAULT_CHUNK_STRATEGY: ChunkStrategy = {\r\n maxTokens: 500,\r\n overlapTokens: 50,\r\n splitBy: 'semantic',\r\n preserveTables: true,\r\n preserveLists: true,\r\n extractHeadings: true,\r\n};\r\n","import type { PrismaClientLike } from '../../types/config.types.js';\r\nimport type {\r\n PromptConfig,\r\n CreatePromptConfig,\r\n PromptConfigFilters,\r\n} from '../../types/prompt.types.js';\r\nimport type { ChunkStrategy } from '../../types/chunk.types.js';\r\nimport { DEFAULT_CHUNK_STRATEGY } from '../../types/prompt.types.js';\r\nimport { DatabaseError, NotFoundError } from '../../errors/index.js';\r\n\r\n/**\r\n * Repository for PromptConfig CRUD operations\r\n */\r\nexport class PromptConfigRepository {\r\n constructor(private readonly prisma: PrismaClientLike) { }\r\n\r\n /**\r\n * Create a new prompt configuration\r\n */\r\n async create(input: CreatePromptConfig): Promise<PromptConfig> {\r\n try {\r\n // Get the next version number for this document type\r\n const latestVersion = await this.prisma.contextRagPromptConfig.findFirst({\r\n where: { documentType: input.documentType },\r\n orderBy: { version: 'desc' },\r\n select: { version: true },\r\n });\r\n\r\n const version = (latestVersion?.version ?? 0) + 1;\r\n\r\n // If setting as default, unset other defaults first\r\n if (input.setAsDefault) {\r\n await this.prisma.contextRagPromptConfig.updateMany({\r\n where: { documentType: input.documentType, isDefault: true },\r\n data: { isDefault: false },\r\n });\r\n }\r\n\r\n // Merge chunk strategy with defaults\r\n const chunkStrategy: ChunkStrategy = {\r\n ...DEFAULT_CHUNK_STRATEGY,\r\n ...input.chunkStrategy,\r\n };\r\n\r\n const created = await this.prisma.contextRagPromptConfig.create({\r\n data: {\r\n documentType: input.documentType,\r\n name: input.name,\r\n systemPrompt: input.systemPrompt,\r\n chunkStrategy,\r\n version,\r\n isActive: true,\r\n isDefault: input.setAsDefault ?? false,\r\n createdBy: 'manual',\r\n changeLog: input.changeLog,\r\n },\r\n });\r\n\r\n return this.mapToPromptConfig(created);\r\n } catch (error) {\r\n throw new DatabaseError('Failed to create prompt config', {\r\n error: (error as Error).message,\r\n documentType: input.documentType,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get a prompt configuration by ID\r\n */\r\n async getById(id: string): Promise<PromptConfig> {\r\n const config = await this.prisma.contextRagPromptConfig.findUnique({\r\n where: { id },\r\n });\r\n\r\n if (!config) {\r\n throw new NotFoundError('PromptConfig', id);\r\n }\r\n\r\n return this.mapToPromptConfig(config);\r\n }\r\n\r\n /**\r\n * Get prompt configurations with optional filters\r\n */\r\n async getMany(filters?: PromptConfigFilters): Promise<PromptConfig[]> {\r\n const where: Record<string, unknown> = {};\r\n\r\n if (filters?.documentType) {\r\n where['documentType'] = filters.documentType;\r\n }\r\n if (filters?.activeOnly) {\r\n where['isActive'] = true;\r\n }\r\n if (filters?.defaultOnly) {\r\n where['isDefault'] = true;\r\n }\r\n if (filters?.createdBy) {\r\n where['createdBy'] = filters.createdBy;\r\n }\r\n\r\n const configs = await this.prisma.contextRagPromptConfig.findMany({\r\n where,\r\n orderBy: [{ documentType: 'asc' }, { version: 'desc' }],\r\n });\r\n\r\n return configs.map((c: Record<string, unknown>) => this.mapToPromptConfig(c));\r\n }\r\n\r\n /**\r\n * Get the active default config for a document type\r\n */\r\n async getDefault(documentType: string): Promise<PromptConfig | null> {\r\n const config = await this.prisma.contextRagPromptConfig.findFirst({\r\n where: {\r\n documentType,\r\n isActive: true,\r\n isDefault: true,\r\n },\r\n });\r\n\r\n return config ? this.mapToPromptConfig(config) : null;\r\n }\r\n\r\n /**\r\n * Get the latest active config for a document type\r\n */\r\n async getLatest(documentType: string): Promise<PromptConfig | null> {\r\n const config = await this.prisma.contextRagPromptConfig.findFirst({\r\n where: {\r\n documentType,\r\n isActive: true,\r\n },\r\n orderBy: { version: 'desc' },\r\n });\r\n\r\n return config ? this.mapToPromptConfig(config) : null;\r\n }\r\n\r\n /**\r\n * Activate a specific config version\r\n */\r\n async activate(id: string): Promise<void> {\r\n const config = await this.prisma.contextRagPromptConfig.findUnique({\r\n where: { id },\r\n });\r\n\r\n if (!config) {\r\n throw new NotFoundError('PromptConfig', id);\r\n }\r\n\r\n // Deactivate all other versions of this document type\r\n await this.prisma.contextRagPromptConfig.updateMany({\r\n where: {\r\n documentType: config.documentType,\r\n id: { not: id },\r\n },\r\n data: { isActive: false, isDefault: false },\r\n });\r\n\r\n // Activate and set as default\r\n await this.prisma.contextRagPromptConfig.update({\r\n where: { id },\r\n data: { isActive: true, isDefault: true },\r\n });\r\n }\r\n\r\n /**\r\n * Deactivate a config\r\n */\r\n async deactivate(id: string): Promise<void> {\r\n await this.prisma.contextRagPromptConfig.update({\r\n where: { id },\r\n data: { isActive: false, isDefault: false },\r\n });\r\n }\r\n\r\n /**\r\n * Delete a config (only if no chunks reference it)\r\n */\r\n async delete(id: string): Promise<void> {\r\n const chunkCount = await this.prisma.contextRagChunk.count({\r\n where: { promptConfigId: id },\r\n });\r\n\r\n if (chunkCount > 0) {\r\n throw new DatabaseError('Cannot delete prompt config with existing chunks', {\r\n id,\r\n chunkCount,\r\n });\r\n }\r\n\r\n await this.prisma.contextRagPromptConfig.delete({\r\n where: { id },\r\n });\r\n }\r\n\r\n /**\r\n * Map database record to PromptConfig type\r\n */\r\n private mapToPromptConfig(record: Record<string, unknown>): PromptConfig {\r\n return {\r\n id: record['id'] as string,\r\n documentType: record['documentType'] as string,\r\n name: record['name'] as string,\r\n systemPrompt: record['systemPrompt'] as string,\r\n chunkStrategy: record['chunkStrategy'] as ChunkStrategy,\r\n version: record['version'] as number,\r\n isActive: record['isActive'] as boolean,\r\n isDefault: record['isDefault'] as boolean,\r\n createdBy: record['createdBy'] as string | undefined,\r\n changeLog: record['changeLog'] as string | undefined,\r\n createdAt: record['createdAt'] as Date,\r\n updatedAt: record['updatedAt'] as Date,\r\n };\r\n }\r\n}\r\n","import type { PrismaClientLike } from '../../types/config.types.js';\r\nimport type { DocumentStatus } from '../../types/ingestion.types.js';\r\nimport type { TokenUsage } from '../../types/chunk.types.js';\r\nimport { DocumentStatusEnum } from '../../types/enums.js';\r\nimport { DatabaseError, NotFoundError } from '../../errors/index.js';\r\n\r\ninterface CreateDocumentInput {\r\n filename: string;\r\n fileHash: string;\r\n fileSize: number;\r\n pageCount: number;\r\n documentType?: string;\r\n promptConfigId?: string;\r\n totalBatches: number;\r\n /** Experiment identifier for A/B testing */\r\n experimentId?: string;\r\n /** Model name used for processing */\r\n modelName?: string;\r\n /** Model configuration (temperature, maxTokens, etc.) */\r\n modelConfig?: Record<string, unknown>;\r\n}\r\n\r\ninterface UpdateDocumentInput {\r\n status?: string;\r\n completedBatches?: number;\r\n failedBatches?: number;\r\n tokenUsage?: TokenUsage;\r\n processingMs?: number;\r\n errorMessage?: string;\r\n completedAt?: Date;\r\n}\r\n\r\n/**\r\n * Repository for Document CRUD operations\r\n */\r\nexport class DocumentRepository {\r\n constructor(private readonly prisma: PrismaClientLike) { }\r\n\r\n /**\r\n * Create a new document record\r\n */\r\n async create(input: CreateDocumentInput): Promise<string> {\r\n try {\r\n const doc = await this.prisma.contextRagDocument.create({\r\n data: {\r\n filename: input.filename,\r\n fileHash: input.fileHash,\r\n fileSize: input.fileSize,\r\n pageCount: input.pageCount,\r\n documentType: input.documentType,\r\n promptConfigId: input.promptConfigId,\r\n status: DocumentStatusEnum.PENDING,\r\n totalBatches: input.totalBatches,\r\n experimentId: input.experimentId,\r\n modelName: input.modelName,\r\n modelConfig: input.modelConfig,\r\n },\r\n });\r\n\r\n return doc.id;\r\n } catch (error) {\r\n // Handle unique constraint violation (duplicate file + experiment)\r\n if ((error as { code?: string }).code === 'P2002') {\r\n throw new DatabaseError('Document with this hash and experimentId already exists', {\r\n fileHash: input.fileHash,\r\n experimentId: input.experimentId,\r\n });\r\n }\r\n throw new DatabaseError('Failed to create document', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get document by ID\r\n */\r\n async getById(id: string): Promise<DocumentStatus> {\r\n const doc = await this.prisma.contextRagDocument.findUnique({\r\n where: { id },\r\n });\r\n\r\n if (!doc) {\r\n throw new NotFoundError('Document', id);\r\n }\r\n\r\n return this.mapToDocumentStatus(doc);\r\n }\r\n\r\n /**\r\n * Get document by file hash (legacy - returns first match)\r\n */\r\n async getByHash(fileHash: string): Promise<DocumentStatus | null> {\r\n const doc = await this.prisma.contextRagDocument.findFirst({\r\n where: { fileHash },\r\n });\r\n\r\n return doc ? this.mapToDocumentStatus(doc) : null;\r\n }\r\n\r\n /**\r\n * Get document by file hash and experiment ID\r\n */\r\n async getByHashAndExperiment(fileHash: string, experimentId?: string): Promise<DocumentStatus | null> {\r\n const doc = await this.prisma.contextRagDocument.findFirst({\r\n where: {\r\n fileHash,\r\n experimentId: experimentId ?? null,\r\n },\r\n });\r\n\r\n return doc ? this.mapToDocumentStatus(doc) : null;\r\n }\r\n\r\n /**\r\n * Update document\r\n */\r\n async update(id: string, input: UpdateDocumentInput): Promise<void> {\r\n await this.prisma.contextRagDocument.update({\r\n where: { id },\r\n data: input,\r\n });\r\n }\r\n\r\n /**\r\n * Increment completed batches count\r\n */\r\n async incrementCompleted(id: string): Promise<void> {\r\n await this.prisma.contextRagDocument.update({\r\n where: { id },\r\n data: {\r\n completedBatches: { increment: 1 },\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Increment failed batches count\r\n */\r\n async incrementFailed(id: string): Promise<void> {\r\n await this.prisma.contextRagDocument.update({\r\n where: { id },\r\n data: {\r\n failedBatches: { increment: 1 },\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Mark document as completed\r\n */\r\n async markCompleted(id: string, tokenUsage: TokenUsage, processingMs: number): Promise<void> {\r\n const doc = await this.prisma.contextRagDocument.findUnique({\r\n where: { id },\r\n select: { failedBatches: true },\r\n });\r\n\r\n const status = doc?.failedBatches > 0\r\n ? DocumentStatusEnum.PARTIAL\r\n : DocumentStatusEnum.COMPLETED;\r\n\r\n await this.prisma.contextRagDocument.update({\r\n where: { id },\r\n data: {\r\n status,\r\n tokenUsage,\r\n processingMs,\r\n completedAt: new Date(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Mark document as failed\r\n */\r\n async markFailed(id: string, errorMessage: string): Promise<void> {\r\n await this.prisma.contextRagDocument.update({\r\n where: { id },\r\n data: {\r\n status: DocumentStatusEnum.FAILED,\r\n errorMessage,\r\n completedAt: new Date(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Delete document and all related data\r\n */\r\n async delete(id: string): Promise<void> {\r\n // Chunks and batches will be cascade deleted\r\n await this.prisma.contextRagDocument.delete({\r\n where: { id },\r\n });\r\n }\r\n\r\n /**\r\n * Get documents by status\r\n */\r\n async getByStatus(status: string): Promise<DocumentStatus[]> {\r\n const docs = await this.prisma.contextRagDocument.findMany({\r\n where: { status },\r\n orderBy: { createdAt: 'desc' },\r\n });\r\n\r\n return docs.map((d: Record<string, unknown>) => this.mapToDocumentStatus(d));\r\n }\r\n\r\n /**\r\n * Map database record to DocumentStatus type\r\n */\r\n private mapToDocumentStatus(record: Record<string, unknown>): DocumentStatus {\r\n const totalBatches = record['totalBatches'] as number;\r\n const completedBatches = record['completedBatches'] as number;\r\n\r\n return {\r\n id: record['id'] as string,\r\n filename: record['filename'] as string,\r\n status: record['status'] as DocumentStatus['status'],\r\n documentType: record['documentType'] as string | undefined,\r\n pageCount: record['pageCount'] as number,\r\n progress: {\r\n totalBatches,\r\n completedBatches,\r\n failedBatches: record['failedBatches'] as number,\r\n percentage: totalBatches > 0 ? Math.round((completedBatches / totalBatches) * 100) : 0,\r\n },\r\n tokenUsage: record['tokenUsage'] as TokenUsage | undefined,\r\n processingMs: record['processingMs'] as number | undefined,\r\n error: record['errorMessage'] as string | undefined,\r\n createdAt: record['createdAt'] as Date,\r\n completedAt: record['completedAt'] as Date | undefined,\r\n };\r\n }\r\n}\r\n","import type { PrismaClientLike } from '../../types/config.types.js';\r\nimport { BatchStatusEnum } from '../../types/enums.js';\r\nimport type { TokenUsage } from '../../types/chunk.types.js';\r\nimport { DatabaseError, NotFoundError } from '../../errors/index.js';\r\n\r\ninterface CreateBatchInput {\r\n documentId: string;\r\n batchIndex: number;\r\n pageStart: number;\r\n pageEnd: number;\r\n}\r\n\r\ninterface BatchRecord {\r\n id: string;\r\n documentId: string;\r\n batchIndex: number;\r\n pageStart: number;\r\n pageEnd: number;\r\n status: string;\r\n retryCount: number;\r\n lastError?: string;\r\n tokenUsage?: TokenUsage;\r\n processingMs?: number;\r\n startedAt?: Date;\r\n completedAt?: Date;\r\n createdAt: Date;\r\n}\r\n\r\n/**\r\n * Repository for Batch CRUD operations\r\n */\r\nexport class BatchRepository {\r\n constructor(private readonly prisma: PrismaClientLike) { }\r\n\r\n /**\r\n * Create multiple batches for a document\r\n */\r\n async createMany(inputs: CreateBatchInput[]): Promise<void> {\r\n try {\r\n await this.prisma.contextRagBatch.createMany({\r\n data: inputs.map(input => ({\r\n documentId: input.documentId,\r\n batchIndex: input.batchIndex,\r\n pageStart: input.pageStart,\r\n pageEnd: input.pageEnd,\r\n status: BatchStatusEnum.PENDING,\r\n })),\r\n });\r\n } catch (error) {\r\n throw new DatabaseError('Failed to create batches', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get batch by ID\r\n */\r\n async getById(id: string): Promise<BatchRecord> {\r\n const batch = await this.prisma.contextRagBatch.findUnique({\r\n where: { id },\r\n });\r\n\r\n if (!batch) {\r\n throw new NotFoundError('Batch', id);\r\n }\r\n\r\n return this.mapToBatchRecord(batch);\r\n }\r\n\r\n /**\r\n * Get all batches for a document\r\n */\r\n async getByDocumentId(documentId: string): Promise<BatchRecord[]> {\r\n const batches = await this.prisma.contextRagBatch.findMany({\r\n where: { documentId },\r\n orderBy: { batchIndex: 'asc' },\r\n });\r\n\r\n return batches.map((b: Record<string, unknown>) => this.mapToBatchRecord(b));\r\n }\r\n\r\n /**\r\n * Get pending batches for a document\r\n */\r\n async getPending(documentId: string): Promise<BatchRecord[]> {\r\n const batches = await this.prisma.contextRagBatch.findMany({\r\n where: {\r\n documentId,\r\n status: BatchStatusEnum.PENDING,\r\n },\r\n orderBy: { batchIndex: 'asc' },\r\n });\r\n\r\n return batches.map((b: Record<string, unknown>) => this.mapToBatchRecord(b));\r\n }\r\n\r\n /**\r\n * Get failed batches for retry\r\n */\r\n async getFailed(documentId: string, maxRetries: number): Promise<BatchRecord[]> {\r\n const batches = await this.prisma.contextRagBatch.findMany({\r\n where: {\r\n documentId,\r\n status: BatchStatusEnum.FAILED,\r\n retryCount: { lt: maxRetries },\r\n },\r\n orderBy: { batchIndex: 'asc' },\r\n });\r\n\r\n return batches.map((b: Record<string, unknown>) => this.mapToBatchRecord(b));\r\n }\r\n\r\n /**\r\n * Mark batch as processing\r\n */\r\n async markProcessing(id: string): Promise<void> {\r\n await this.prisma.contextRagBatch.update({\r\n where: { id },\r\n data: {\r\n status: BatchStatusEnum.PROCESSING,\r\n startedAt: new Date(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Mark batch as retrying\r\n */\r\n async markRetrying(id: string, error: string): Promise<void> {\r\n await this.prisma.contextRagBatch.update({\r\n where: { id },\r\n data: {\r\n status: BatchStatusEnum.RETRYING,\r\n lastError: error,\r\n retryCount: { increment: 1 },\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Mark batch as completed\r\n */\r\n async markCompleted(\r\n id: string,\r\n tokenUsage: TokenUsage,\r\n processingMs: number\r\n ): Promise<void> {\r\n await this.prisma.contextRagBatch.update({\r\n where: { id },\r\n data: {\r\n status: BatchStatusEnum.COMPLETED,\r\n tokenUsage,\r\n processingMs,\r\n completedAt: new Date(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Mark batch as failed\r\n */\r\n async markFailed(id: string, error: string): Promise<void> {\r\n await this.prisma.contextRagBatch.update({\r\n where: { id },\r\n data: {\r\n status: BatchStatusEnum.FAILED,\r\n lastError: error,\r\n completedAt: new Date(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Reset batch for retry (set back to pending)\r\n */\r\n async resetForRetry(id: string): Promise<void> {\r\n await this.prisma.contextRagBatch.update({\r\n where: { id },\r\n data: {\r\n status: BatchStatusEnum.PENDING,\r\n startedAt: null,\r\n completedAt: null,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Map database record to BatchRecord type\r\n */\r\n private mapToBatchRecord(record: Record<string, unknown>): BatchRecord {\r\n return {\r\n id: record['id'] as string,\r\n documentId: record['documentId'] as string,\r\n batchIndex: record['batchIndex'] as number,\r\n pageStart: record['pageStart'] as number,\r\n pageEnd: record['pageEnd'] as number,\r\n status: record['status'] as string,\r\n retryCount: record['retryCount'] as number,\r\n lastError: record['lastError'] as string | undefined,\r\n tokenUsage: record['tokenUsage'] as TokenUsage | undefined,\r\n processingMs: record['processingMs'] as number | undefined,\r\n startedAt: record['startedAt'] as Date | undefined,\r\n completedAt: record['completedAt'] as Date | undefined,\r\n createdAt: record['createdAt'] as Date,\r\n };\r\n }\r\n}\r\n","import type { PrismaClientLike } from '../../types/config.types.js';\r\nimport type { VectorChunk, CreateChunkInput, ChunkType } from '../../types/chunk.types.js';\r\nimport type { SearchFilters } from '../../types/search.types.js';\r\nimport { DatabaseError } from '../../errors/index.js';\r\n\r\ninterface ChunkSearchResult {\r\n chunk: VectorChunk;\r\n similarity: number;\r\n}\r\n\r\n/**\r\n * Repository for Chunk CRUD and search operations\r\n */\r\nexport class ChunkRepository {\r\n constructor(private readonly prisma: PrismaClientLike) { }\r\n\r\n /**\r\n * Create a single chunk with embedding\r\n */\r\n async create(input: CreateChunkInput, embedding: number[]): Promise<string> {\r\n try {\r\n // Use raw query for vector insertion\r\n const result = await this.prisma.$queryRaw`\r\n INSERT INTO context_rag_chunks (\r\n id, prompt_config_id, document_id, chunk_index, chunk_type,\r\n search_content, search_vector, display_content,\r\n source_page_start, source_page_end, confidence_score, metadata, created_at\r\n ) VALUES (\r\n gen_random_uuid(),\r\n ${input.promptConfigId},\r\n ${input.documentId},\r\n ${input.chunkIndex},\r\n ${input.chunkType},\r\n ${input.searchContent},\r\n ${embedding}::vector,\r\n ${input.displayContent},\r\n ${input.sourcePageStart},\r\n ${input.sourcePageEnd},\r\n ${input.confidenceScore},\r\n ${JSON.stringify(input.metadata)}::jsonb,\r\n NOW()\r\n )\r\n RETURNING id\r\n `;\r\n\r\n return (result as Array<{ id: string }>)[0]?.id ?? '';\r\n } catch (error) {\r\n throw new DatabaseError('Failed to create chunk', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Create multiple chunks with embeddings\r\n */\r\n async createMany(\r\n inputs: CreateChunkInput[],\r\n embeddings: number[][]\r\n ): Promise<string[]> {\r\n const ids: string[] = [];\r\n\r\n // Process in transaction\r\n await this.prisma.$transaction(async (tx: PrismaClientLike) => {\r\n for (let i = 0; i < inputs.length; i++) {\r\n const input = inputs[i];\r\n const embedding = embeddings[i];\r\n\r\n if (!input || !embedding) continue;\r\n\r\n const result = await tx.$queryRaw`\r\n INSERT INTO context_rag_chunks (\r\n id, prompt_config_id, document_id, chunk_index, chunk_type,\r\n search_content, search_vector, display_content,\r\n source_page_start, source_page_end, confidence_score, metadata, created_at\r\n ) VALUES (\r\n gen_random_uuid(),\r\n ${input.promptConfigId},\r\n ${input.documentId},\r\n ${input.chunkIndex},\r\n ${input.chunkType},\r\n ${input.searchContent},\r\n ${embedding}::vector,\r\n ${input.displayContent},\r\n ${input.sourcePageStart},\r\n ${input.sourcePageEnd},\r\n ${input.confidenceScore},\r\n ${JSON.stringify(input.metadata)}::jsonb,\r\n NOW()\r\n )\r\n RETURNING id\r\n `;\r\n\r\n const id = (result as Array<{ id: string }>)[0]?.id;\r\n if (id) ids.push(id);\r\n }\r\n });\r\n\r\n return ids;\r\n }\r\n\r\n /**\r\n * Vector similarity search\r\n */\r\n async searchSemantic(\r\n queryEmbedding: number[],\r\n limit: number,\r\n filters?: SearchFilters,\r\n minScore?: number\r\n ): Promise<ChunkSearchResult[]> {\r\n const whereConditions: string[] = [];\r\n const params: unknown[] = [queryEmbedding, limit];\r\n let paramIndex = 3;\r\n\r\n // Build filter conditions\r\n if (filters?.documentTypes?.length) {\r\n whereConditions.push(`c.document_id IN (\r\n SELECT id FROM context_rag_documents WHERE document_type = ANY($${paramIndex})\r\n )`);\r\n params.push(filters.documentTypes);\r\n paramIndex++;\r\n }\r\n\r\n if (filters?.chunkTypes?.length) {\r\n whereConditions.push(`c.chunk_type = ANY($${paramIndex})`);\r\n params.push(filters.chunkTypes);\r\n paramIndex++;\r\n }\r\n\r\n if (filters?.minConfidence !== undefined) {\r\n whereConditions.push(`c.confidence_score >= $${paramIndex}`);\r\n params.push(filters.minConfidence);\r\n paramIndex++;\r\n }\r\n\r\n if (filters?.documentIds?.length) {\r\n whereConditions.push(`c.document_id = ANY($${paramIndex})`);\r\n params.push(filters.documentIds);\r\n paramIndex++;\r\n }\r\n\r\n if (filters?.promptConfigIds?.length) {\r\n whereConditions.push(`c.prompt_config_id = ANY($${paramIndex})`);\r\n params.push(filters.promptConfigIds);\r\n paramIndex++;\r\n }\r\n\r\n const whereClause = whereConditions.length > 0\r\n ? `WHERE ${whereConditions.join(' AND ')}`\r\n : '';\r\n\r\n const scoreThreshold = minScore !== undefined\r\n ? `HAVING 1 - (c.search_vector <=> $1::vector) >= ${minScore}`\r\n : '';\r\n\r\n const query = `\r\n SELECT \r\n c.id, c.prompt_config_id, c.document_id, c.chunk_index, c.chunk_type,\r\n c.search_content, c.display_content,\r\n c.source_page_start, c.source_page_end, c.confidence_score,\r\n c.metadata, c.created_at,\r\n 1 - (c.search_vector <=> $1::vector) as similarity\r\n FROM context_rag_chunks c\r\n ${whereClause}\r\n GROUP BY c.id\r\n ${scoreThreshold}\r\n ORDER BY c.search_vector <=> $1::vector\r\n LIMIT $2\r\n `;\r\n\r\n const results = await this.prisma.$queryRawUnsafe(query, ...params);\r\n\r\n return (results as Array<Record<string, unknown>>).map(row => ({\r\n chunk: this.mapToVectorChunk(row),\r\n similarity: row['similarity'] as number,\r\n }));\r\n }\r\n\r\n /**\r\n * Full-text keyword search\r\n */\r\n async searchKeyword(\r\n query: string,\r\n limit: number,\r\n filters?: SearchFilters\r\n ): Promise<ChunkSearchResult[]> {\r\n const whereConditions: string[] = [\r\n `to_tsvector('english', c.search_content) @@ plainto_tsquery('english', $1)`\r\n ];\r\n const params: unknown[] = [query, limit];\r\n let paramIndex = 3;\r\n\r\n // Build filter conditions (same as semantic)\r\n if (filters?.chunkTypes?.length) {\r\n whereConditions.push(`c.chunk_type = ANY($${paramIndex})`);\r\n params.push(filters.chunkTypes);\r\n paramIndex++;\r\n }\r\n\r\n if (filters?.documentIds?.length) {\r\n whereConditions.push(`c.document_id = ANY($${paramIndex})`);\r\n params.push(filters.documentIds);\r\n paramIndex++;\r\n }\r\n\r\n const whereClause = `WHERE ${whereConditions.join(' AND ')}`;\r\n\r\n const queryStr = `\r\n SELECT \r\n c.id, c.prompt_config_id, c.document_id, c.chunk_index, c.chunk_type,\r\n c.search_content, c.display_content,\r\n c.source_page_start, c.source_page_end, c.confidence_score,\r\n c.metadata, c.created_at,\r\n ts_rank(to_tsvector('english', c.search_content), plainto_tsquery('english', $1)) as similarity\r\n FROM context_rag_chunks c\r\n ${whereClause}\r\n ORDER BY similarity DESC\r\n LIMIT $2\r\n `;\r\n\r\n const results = await this.prisma.$queryRawUnsafe(queryStr, ...params);\r\n\r\n return (results as Array<Record<string, unknown>>).map(row => ({\r\n chunk: this.mapToVectorChunk(row),\r\n similarity: row['similarity'] as number,\r\n }));\r\n }\r\n\r\n /**\r\n * Get chunks by document ID\r\n */\r\n async getByDocumentId(documentId: string): Promise<VectorChunk[]> {\r\n const chunks = await this.prisma.contextRagChunk.findMany({\r\n where: { documentId },\r\n orderBy: { chunkIndex: 'asc' },\r\n });\r\n\r\n return chunks.map((c: Record<string, unknown>) => this.mapToVectorChunk(c));\r\n }\r\n\r\n /**\r\n * Delete chunks by document ID\r\n */\r\n async deleteByDocumentId(documentId: string): Promise<number> {\r\n const result = await this.prisma.contextRagChunk.deleteMany({\r\n where: { documentId },\r\n });\r\n\r\n return result.count;\r\n }\r\n\r\n /**\r\n * Count chunks by document ID\r\n */\r\n async countByDocumentId(documentId: string): Promise<number> {\r\n return await this.prisma.contextRagChunk.count({\r\n where: { documentId },\r\n });\r\n }\r\n\r\n /**\r\n * Map database record to VectorChunk type\r\n */\r\n private mapToVectorChunk(record: Record<string, unknown>): VectorChunk {\r\n return {\r\n id: record['id'] as string,\r\n promptConfigId: (record['prompt_config_id'] ?? record['promptConfigId']) as string,\r\n documentId: (record['document_id'] ?? record['documentId']) as string,\r\n chunkIndex: (record['chunk_index'] ?? record['chunkIndex']) as number,\r\n chunkType: (record['chunk_type'] ?? record['chunkType']) as ChunkType,\r\n searchContent: (record['search_content'] ?? record['searchContent']) as string,\r\n displayContent: (record['display_content'] ?? record['displayContent']) as string,\r\n sourcePageStart: (record['source_page_start'] ?? record['sourcePageStart']) as number,\r\n sourcePageEnd: (record['source_page_end'] ?? record['sourcePageEnd']) as number,\r\n confidenceScore: (record['confidence_score'] ?? record['confidenceScore']) as number,\r\n metadata: record['metadata'] as VectorChunk['metadata'],\r\n createdAt: (record['created_at'] ?? record['createdAt']) as Date,\r\n };\r\n }\r\n}\r\n","import type { PrismaClientLike } from '../types/config.types.js';\r\nimport { DatabaseError } from '../errors/index.js';\r\n\r\n/**\r\n * Check if pgvector extension is installed in the database\r\n */\r\nexport async function checkPgVectorExtension(prisma: PrismaClientLike): Promise<boolean> {\r\n try {\r\n const result = await prisma.$queryRaw`\r\n SELECT EXISTS (\r\n SELECT 1 FROM pg_extension WHERE extname = 'vector'\r\n ) as exists\r\n `;\r\n\r\n return (result as Array<{ exists: boolean }>)[0]?.exists ?? false;\r\n } catch (error) {\r\n throw new DatabaseError('Failed to check pgvector extension', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Install pgvector extension (requires superuser privileges)\r\n */\r\nexport async function installPgVectorExtension(prisma: PrismaClientLike): Promise<void> {\r\n try {\r\n await prisma.$executeRaw`CREATE EXTENSION IF NOT EXISTS vector`;\r\n } catch (error) {\r\n throw new DatabaseError(\r\n 'Failed to install pgvector extension. Make sure you have superuser privileges.',\r\n { error: (error as Error).message }\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Check database connection\r\n */\r\nexport async function checkDatabaseConnection(prisma: PrismaClientLike): Promise<boolean> {\r\n try {\r\n await prisma.$queryRaw`SELECT 1`;\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get database statistics for Context-RAG tables\r\n */\r\nexport async function getDatabaseStats(prisma: PrismaClientLike): Promise<{\r\n documents: number;\r\n chunks: number;\r\n promptConfigs: number;\r\n batches: number;\r\n totalStorageBytes: number;\r\n}> {\r\n try {\r\n const [documents, chunks, promptConfigs, batches] = await Promise.all([\r\n prisma.contextRagDocument.count(),\r\n prisma.contextRagChunk.count(),\r\n prisma.contextRagPromptConfig.count(),\r\n prisma.contextRagBatch.count(),\r\n ]);\r\n\r\n // Get storage size\r\n const storageResult = await prisma.$queryRaw`\r\n SELECT \r\n COALESCE(SUM(pg_total_relation_size(quote_ident(tablename)::regclass)), 0) as total_bytes\r\n FROM pg_tables\r\n WHERE tablename LIKE 'context_rag_%'\r\n `;\r\n\r\n const totalStorageBytes = Number((storageResult as Array<{ total_bytes: bigint }>)[0]?.total_bytes ?? 0);\r\n\r\n return {\r\n documents,\r\n chunks,\r\n promptConfigs,\r\n batches,\r\n totalStorageBytes,\r\n };\r\n } catch (error) {\r\n throw new DatabaseError('Failed to get database stats', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Vacuum and analyze Context-RAG tables for performance\r\n */\r\nexport async function optimizeTables(prisma: PrismaClientLike): Promise<void> {\r\n try {\r\n await prisma.$executeRaw`VACUUM ANALYZE context_rag_chunks`;\r\n await prisma.$executeRaw`VACUUM ANALYZE context_rag_documents`;\r\n await prisma.$executeRaw`VACUUM ANALYZE context_rag_batches`;\r\n await prisma.$executeRaw`VACUUM ANALYZE context_rag_prompt_configs`;\r\n } catch (error) {\r\n throw new DatabaseError('Failed to optimize tables', {\r\n error: (error as Error).message,\r\n });\r\n }\r\n}\r\n","import { GoogleGenerativeAI, type GenerativeModel, type Part, TaskType } from '@google/generative-ai';\r\nimport { GoogleAIFileManager } from '@google/generative-ai/server';\r\nimport type { ResolvedConfig } from '../types/config.types.js';\r\nimport type { TokenUsage } from '../types/chunk.types.js';\r\nimport { RateLimitError } from '../errors/index.js';\r\nimport { RateLimiter } from '../utils/rate-limiter.js';\r\nimport type { Logger } from '../utils/logger.js';\r\n\r\n/**\r\n * Response from Gemini API\r\n */\r\nexport interface GeminiResponse {\r\n text: string;\r\n tokenUsage: TokenUsage;\r\n}\r\n\r\n/**\r\n * Embedding response\r\n */\r\nexport interface EmbeddingResponse {\r\n embedding: number[];\r\n tokenCount: number;\r\n}\r\n\r\n/**\r\n * Embedding task type for optimized embeddings\r\n * @see https://ai.google.dev/gemini-api/docs/embeddings\r\n */\r\nexport type EmbeddingTaskType =\r\n | 'RETRIEVAL_DOCUMENT' // For documents to be indexed\r\n | 'RETRIEVAL_QUERY' // For search queries\r\n | 'SEMANTIC_SIMILARITY' // For similarity comparison\r\n | 'CLASSIFICATION' // For classification tasks\r\n | 'CLUSTERING'; // For clustering tasks\r\n\r\n/**\r\n * Gemini API service wrapper\r\n */\r\nexport class GeminiService {\r\n private readonly genAI: GoogleGenerativeAI;\r\n private readonly fileManager: GoogleAIFileManager;\r\n private readonly model: GenerativeModel;\r\n private readonly embeddingModel: GenerativeModel;\r\n private readonly config: ResolvedConfig;\r\n private readonly rateLimiter: RateLimiter;\r\n private readonly logger: Logger;\r\n\r\n constructor(config: ResolvedConfig, rateLimiter: RateLimiter, logger: Logger) {\r\n this.genAI = new GoogleGenerativeAI(config.geminiApiKey);\r\n this.fileManager = new GoogleAIFileManager(config.geminiApiKey);\r\n this.model = this.genAI.getGenerativeModel({ model: config.model });\r\n this.embeddingModel = this.genAI.getGenerativeModel({ model: config.embeddingModel });\r\n this.config = config;\r\n this.rateLimiter = rateLimiter;\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Generate text content\r\n */\r\n async generate(\r\n systemPrompt: string,\r\n userContent: string,\r\n options?: {\r\n temperature?: number;\r\n maxOutputTokens?: number;\r\n }\r\n ): Promise<GeminiResponse> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.model.generateContent({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [{ text: `${systemPrompt}\\n\\n${userContent}` }],\r\n },\r\n ],\r\n generationConfig: {\r\n temperature: options?.temperature ?? this.config.generationConfig.temperature,\r\n maxOutputTokens: options?.maxOutputTokens ?? this.config.generationConfig.maxOutputTokens,\r\n },\r\n });\r\n\r\n const response = result.response;\r\n const text = response.text();\r\n const usage = response.usageMetadata;\r\n\r\n this.rateLimiter.reportSuccess();\r\n\r\n return {\r\n text,\r\n tokenUsage: {\r\n input: usage?.promptTokenCount ?? 0,\r\n output: usage?.candidatesTokenCount ?? 0,\r\n total: usage?.totalTokenCount ?? 0,\r\n },\r\n };\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Generate content with vision (PDF pages as images)\r\n */\r\n async generateWithVision(\r\n systemPrompt: string,\r\n parts: Part[],\r\n options?: {\r\n temperature?: number;\r\n maxOutputTokens?: number;\r\n }\r\n ): Promise<GeminiResponse> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.model.generateContent({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [{ text: systemPrompt }, ...parts],\r\n },\r\n ],\r\n generationConfig: {\r\n temperature: options?.temperature ?? this.config.generationConfig.temperature,\r\n maxOutputTokens: options?.maxOutputTokens ?? this.config.generationConfig.maxOutputTokens,\r\n },\r\n });\r\n\r\n const response = result.response;\r\n const text = response.text();\r\n const usage = response.usageMetadata;\r\n\r\n this.rateLimiter.reportSuccess();\r\n\r\n return {\r\n text,\r\n tokenUsage: {\r\n input: usage?.promptTokenCount ?? 0,\r\n output: usage?.candidatesTokenCount ?? 0,\r\n total: usage?.totalTokenCount ?? 0,\r\n },\r\n };\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Generate embeddings for text with task type\r\n * \r\n * Best practices:\r\n * - Use RETRIEVAL_DOCUMENT for documents being indexed\r\n * - Use RETRIEVAL_QUERY for search queries\r\n * \r\n * @see https://ai.google.dev/gemini-api/docs/embeddings\r\n */\r\n async embed(\r\n text: string,\r\n taskType: EmbeddingTaskType = 'RETRIEVAL_DOCUMENT'\r\n ): Promise<EmbeddingResponse> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.embeddingModel.embedContent({\r\n content: { parts: [{ text }], role: 'user' },\r\n taskType: this.mapTaskType(taskType),\r\n });\r\n\r\n this.rateLimiter.reportSuccess();\r\n\r\n return {\r\n embedding: result.embedding.values,\r\n tokenCount: text.split(/\\s+/).length, // Approximate\r\n };\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Generate embeddings for documents (for indexing)\r\n * Uses RETRIEVAL_DOCUMENT task type\r\n */\r\n async embedDocument(text: string): Promise<EmbeddingResponse> {\r\n return this.embed(text, 'RETRIEVAL_DOCUMENT');\r\n }\r\n\r\n /**\r\n * Generate embeddings for search query\r\n * Uses RETRIEVAL_QUERY task type\r\n */\r\n async embedQuery(text: string): Promise<EmbeddingResponse> {\r\n return this.embed(text, 'RETRIEVAL_QUERY');\r\n }\r\n\r\n /**\r\n * Generate embeddings for multiple documents (batch)\r\n * Uses RETRIEVAL_DOCUMENT task type\r\n */\r\n async embedBatch(texts: string[]): Promise<EmbeddingResponse[]> {\r\n const results: EmbeddingResponse[] = [];\r\n\r\n for (const text of texts) {\r\n const result = await this.embedDocument(text);\r\n results.push(result);\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Map our task type enum to Gemini's TaskType\r\n */\r\n private mapTaskType(taskType: EmbeddingTaskType): TaskType {\r\n const mapping: Record<EmbeddingTaskType, TaskType> = {\r\n 'RETRIEVAL_DOCUMENT': TaskType.RETRIEVAL_DOCUMENT,\r\n 'RETRIEVAL_QUERY': TaskType.RETRIEVAL_QUERY,\r\n 'SEMANTIC_SIMILARITY': TaskType.SEMANTIC_SIMILARITY,\r\n 'CLASSIFICATION': TaskType.CLASSIFICATION,\r\n 'CLUSTERING': TaskType.CLUSTERING,\r\n };\r\n return mapping[taskType];\r\n }\r\n\r\n /**\r\n * Simple text generation (single prompt)\r\n * Used for context generation in RAG enhancement\r\n */\r\n async generateSimple(prompt: string): Promise<string> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.model.generateContent({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [{ text: prompt }],\r\n },\r\n ],\r\n generationConfig: {\r\n temperature: 0.3,\r\n maxOutputTokens: 200, // Short context\r\n },\r\n });\r\n\r\n this.rateLimiter.reportSuccess();\r\n return result.response.text().trim();\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Generate content with file reference (for contextual retrieval)\r\n * Uses Gemini's file caching for efficiency\r\n */\r\n async generateWithFileRef(fileUri: string, prompt: string): Promise<string> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.model.generateContent({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [\r\n { fileData: { mimeType: 'application/pdf', fileUri } },\r\n { text: prompt },\r\n ],\r\n },\r\n ],\r\n generationConfig: {\r\n temperature: 0.3,\r\n maxOutputTokens: 200,\r\n },\r\n });\r\n\r\n this.rateLimiter.reportSuccess();\r\n return result.response.text().trim();\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Upload PDF buffer to Gemini Files API\r\n * Returns file URI for use in subsequent requests\r\n * File is cached by Gemini for efficient reuse\r\n */\r\n async uploadPdfBuffer(buffer: Buffer, filename: string): Promise<string> {\r\n try {\r\n // Write buffer to temp file (FileManager requires file path)\r\n const fs = await import('fs');\r\n const path = await import('path');\r\n const os = await import('os');\r\n\r\n const tempPath = path.join(os.tmpdir(), `context-rag-${Date.now()}-${filename}`);\r\n fs.writeFileSync(tempPath, buffer);\r\n\r\n this.logger.info('Uploading PDF to Gemini Files API', { filename });\r\n\r\n const uploadResult = await this.fileManager.uploadFile(tempPath, {\r\n mimeType: 'application/pdf',\r\n displayName: filename,\r\n });\r\n\r\n // Cleanup temp file\r\n fs.unlinkSync(tempPath);\r\n\r\n this.logger.info('PDF uploaded successfully', {\r\n fileUri: uploadResult.file.uri,\r\n displayName: uploadResult.file.displayName,\r\n });\r\n\r\n return uploadResult.file.uri;\r\n } catch (error) {\r\n this.logger.error('Failed to upload PDF', { error: (error as Error).message });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Generate content using uploaded PDF URI\r\n * Uses Gemini's file caching for efficient context generation\r\n */\r\n async generateWithPdfUri(\r\n pdfUri: string,\r\n prompt: string,\r\n options?: {\r\n temperature?: number;\r\n maxOutputTokens?: number;\r\n }\r\n ): Promise<GeminiResponse> {\r\n await this.rateLimiter.acquire();\r\n\r\n try {\r\n const result = await this.model.generateContent({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [\r\n { fileData: { mimeType: 'application/pdf', fileUri: pdfUri } },\r\n { text: prompt },\r\n ],\r\n },\r\n ],\r\n generationConfig: {\r\n temperature: options?.temperature ?? 0.3,\r\n maxOutputTokens: options?.maxOutputTokens ?? 200,\r\n },\r\n });\r\n\r\n const response = result.response;\r\n const text = response.text().trim();\r\n const usage = response.usageMetadata;\r\n\r\n this.rateLimiter.reportSuccess();\r\n\r\n return {\r\n text,\r\n tokenUsage: {\r\n input: usage?.promptTokenCount ?? 0,\r\n output: usage?.candidatesTokenCount ?? 0,\r\n total: usage?.totalTokenCount ?? 0,\r\n },\r\n };\r\n } catch (error) {\r\n this.handleError(error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Handle API errors\r\n */\r\n private handleError(error: Error): void {\r\n const message = error.message.toLowerCase();\r\n\r\n if (message.includes('429') || message.includes('rate limit')) {\r\n this.rateLimiter.reportRateLimitError();\r\n throw new RateLimitError('Gemini API rate limit exceeded');\r\n }\r\n\r\n this.logger.error('Gemini API error', {\r\n error: error.message,\r\n });\r\n }\r\n}\r\n","import * as fs from 'fs/promises';\r\nimport * as path from 'path';\r\nimport type { Part } from '@google/generative-ai';\r\nimport pdf from 'pdf-parse';\r\nimport { hashBuffer } from '../utils/hash.js';\r\nimport type { Logger } from '../utils/logger.js';\r\n\r\n/**\r\n * PDF document metadata\r\n */\r\nexport interface PDFMetadata {\r\n filename: string;\r\n fileHash: string;\r\n fileSize: number;\r\n pageCount: number;\r\n title?: string;\r\n author?: string;\r\n}\r\n\r\n/**\r\n * Page content extract\r\n */\r\nexport interface PageContent {\r\n pageNumber: number;\r\n text: string;\r\n}\r\n\r\n/**\r\n * Batch of pages for processing\r\n */\r\nexport interface PageBatch {\r\n batchIndex: number;\r\n pageStart: number;\r\n pageEnd: number;\r\n pages: PageContent[];\r\n}\r\n\r\n/**\r\n * PDF processing service\r\n */\r\nexport class PDFProcessor {\r\n private readonly logger: Logger;\r\n\r\n constructor(logger: Logger) {\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Load PDF from file path or buffer\r\n */\r\n async load(input: Buffer | string): Promise<{\r\n buffer: Buffer;\r\n metadata: PDFMetadata;\r\n }> {\r\n let buffer: Buffer;\r\n let filename: string;\r\n\r\n if (typeof input === 'string') {\r\n // File path\r\n buffer = await fs.readFile(input);\r\n filename = path.basename(input);\r\n } else {\r\n // Buffer\r\n buffer = input;\r\n filename = 'document.pdf';\r\n }\r\n\r\n const fileHash = hashBuffer(buffer);\r\n const fileSize = buffer.length;\r\n\r\n // Parse PDF to get page count\r\n const pdfData = await pdf(buffer);\r\n const pageCount = pdfData.numpages;\r\n\r\n this.logger.debug('PDF loaded', {\r\n filename,\r\n fileSize,\r\n pageCount,\r\n });\r\n\r\n return {\r\n buffer,\r\n metadata: {\r\n filename,\r\n fileHash,\r\n fileSize,\r\n pageCount,\r\n title: pdfData.info?.Title,\r\n author: pdfData.info?.Author,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Extract text from all pages\r\n */\r\n async extractText(buffer: Buffer): Promise<PageContent[]> {\r\n const pdfData = await pdf(buffer);\r\n\r\n // pdf-parse returns all text combined, we need to split by pages\r\n // This is a limitation - for actual page splitting, we'd need pdf.js\r\n // For now, return as single page\r\n return [{\r\n pageNumber: 1,\r\n text: pdfData.text,\r\n }];\r\n }\r\n\r\n /**\r\n * Convert PDF buffer to base64 for Gemini Vision API\r\n */\r\n toBase64(buffer: Buffer): string {\r\n return buffer.toString('base64');\r\n }\r\n\r\n /**\r\n * Create Gemini vision part from PDF\r\n */\r\n createVisionPart(buffer: Buffer): Part {\r\n return {\r\n inlineData: {\r\n mimeType: 'application/pdf',\r\n data: this.toBase64(buffer),\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Split document into batches\r\n */\r\n createBatches(pageCount: number, pagesPerBatch: number): Array<{\r\n batchIndex: number;\r\n pageStart: number;\r\n pageEnd: number;\r\n }> {\r\n const batches: Array<{\r\n batchIndex: number;\r\n pageStart: number;\r\n pageEnd: number;\r\n }> = [];\r\n\r\n for (let i = 0; i < pageCount; i += pagesPerBatch) {\r\n batches.push({\r\n batchIndex: batches.length,\r\n pageStart: i + 1, // 1-indexed\r\n pageEnd: Math.min(i + pagesPerBatch, pageCount),\r\n });\r\n }\r\n\r\n this.logger.debug('Created batches', {\r\n pageCount,\r\n pagesPerBatch,\r\n batchCount: batches.length,\r\n });\r\n\r\n return batches;\r\n }\r\n\r\n /**\r\n * Get page range description for prompts\r\n */\r\n getPageRangeDescription(pageStart: number, pageEnd: number): string {\r\n if (pageStart === pageEnd) {\r\n return `page ${pageStart}`;\r\n }\r\n return `pages ${pageStart}-${pageEnd}`;\r\n }\r\n}\r\n","/**\r\n * No-Op Enhancement Handler\r\n * \r\n * Default handler that does nothing - maintains backward compatibility.\r\n */\r\n\r\nimport type { EnhancementHandler } from '../types/rag-enhancement.types.js';\r\n\r\nexport class NoOpHandler implements EnhancementHandler {\r\n shouldSkip(): boolean {\r\n return true; // Skip all - no context generation\r\n }\r\n\r\n async generateContext(): Promise<string> {\r\n return '';\r\n }\r\n}\r\n","/**\r\n * RAG Enhancement Types\r\n * \r\n * Hierarchical architecture for different RAG enhancement approaches.\r\n * Supports Anthropic Contextual Retrieval, future Google Grounding, and custom handlers.\r\n */\r\n\r\n// ===== CHUNK DATA (for handlers) =====\r\n\r\nexport interface ChunkData {\r\n content: string;\r\n searchContent: string;\r\n displayContent: string;\r\n chunkType: string;\r\n page: number;\r\n parentHeading?: string;\r\n}\r\n\r\nexport interface DocumentContext {\r\n documentType?: string;\r\n filename: string;\r\n pageCount: number;\r\n /** For LLM strategy: uploaded file URI (Gemini Files API) */\r\n fileUri?: string;\r\n /** For LLM strategy: full document text for context (Anthropic-style, max 15k chars) */\r\n fullDocumentText?: string;\r\n}\r\n\r\n// ===== RAG APPROACH TYPES =====\r\n\r\nexport type RagApproach =\r\n | 'none'\r\n | 'anthropic_contextual'\r\n | 'google_grounding' // Future\r\n | 'custom';\r\n\r\n// ===== NO ENHANCEMENT =====\r\n\r\nexport interface NoEnhancementConfig {\r\n approach: 'none';\r\n}\r\n\r\n// ===== ANTHROPIC CONTEXTUAL RETRIEVAL =====\r\n\r\nexport type AnthropicStrategy = 'none' | 'simple' | 'llm';\r\n\r\nexport interface AnthropicContextualConfig {\r\n approach: 'anthropic_contextual';\r\n strategy: AnthropicStrategy;\r\n\r\n /** For 'simple': template pattern\r\n * Available placeholders: {documentType}, {chunkType}, {page}, {parentHeading}\r\n * Example: \"[{documentType}] [{chunkType}] Page {page}\"\r\n */\r\n template?: string;\r\n\r\n /** For 'llm': context generation prompt */\r\n contextPrompt?: string;\r\n\r\n /** For 'llm': max tokens for generated context (default: 100) */\r\n maxContextTokens?: number;\r\n\r\n /** Chunk types to skip context generation for (default: ['HEADING', 'IMAGE_REF']) */\r\n skipChunkTypes?: string[];\r\n\r\n /** Max concurrent LLM calls (default: 5) */\r\n concurrencyLimit?: number;\r\n\r\n /** Enable caching to avoid duplicate API calls (default: true) */\r\n enableCache?: boolean;\r\n}\r\n\r\n// ===== GOOGLE GROUNDING (Future) =====\r\n\r\nexport type GoogleGroundingStrategy = 'search' | 'factcheck';\r\n\r\nexport interface GoogleGroundingConfig {\r\n approach: 'google_grounding';\r\n strategy: GoogleGroundingStrategy;\r\n // Future config options\r\n}\r\n\r\n// ===== CUSTOM ENHANCEMENT =====\r\n\r\nexport interface EnhancementContext {\r\n chunk: ChunkData;\r\n doc: DocumentContext;\r\n}\r\n\r\nexport type CustomEnhancementHandler = (ctx: EnhancementContext) => Promise<string>;\r\n\r\nexport interface CustomEnhancementConfig {\r\n approach: 'custom';\r\n handler: CustomEnhancementHandler;\r\n\r\n /** Chunk types to skip (optional) */\r\n skipChunkTypes?: string[];\r\n}\r\n\r\n// ===== UNION TYPE =====\r\n\r\nexport type RagEnhancementConfig =\r\n | NoEnhancementConfig\r\n | AnthropicContextualConfig\r\n | GoogleGroundingConfig\r\n | CustomEnhancementConfig;\r\n\r\n// ===== ENHANCEMENT HANDLER INTERFACE =====\r\n\r\nexport interface EnhancementHandler {\r\n /**\r\n * Generate context for a chunk\r\n * @returns Context string to prepend to searchContent, or empty string\r\n */\r\n generateContext(chunk: ChunkData, doc: DocumentContext): Promise<string>;\r\n\r\n /**\r\n * Check if this chunk type should be skipped\r\n */\r\n shouldSkip(chunkType: string): boolean;\r\n}\r\n\r\n// ===== DEFAULT VALUES =====\r\n\r\nexport const DEFAULT_ANTHROPIC_CONFIG = {\r\n maxContextTokens: 100,\r\n skipChunkTypes: ['HEADING', 'IMAGE_REF'],\r\n concurrencyLimit: 5,\r\n enableCache: true,\r\n template: '[{documentType}] [{chunkType}] Page {page}',\r\n contextPrompt: 'Bu parçayı belgede konumlandır. Parçanın ne hakkında olduğunu ve belgede nerede bulunduğunu 1-2 cümle ile Türkçe açıkla:',\r\n} as const;\r\n","/**\r\n * Anthropic Contextual Retrieval Handler\r\n * \r\n * Implements Anthropic's Contextual Retrieval approach with 3 strategies:\r\n * - none: No context generation\r\n * - simple: Template-based context (free)\r\n * - llm: LLM-generated context (best quality, costs ~$0.005/chunk)\r\n */\r\n\r\nimport type {\r\n AnthropicContextualConfig,\r\n EnhancementHandler,\r\n ChunkData,\r\n DocumentContext\r\n} from '../../types/rag-enhancement.types.js';\r\nimport { DEFAULT_ANTHROPIC_CONFIG as DEFAULTS } from '../../types/rag-enhancement.types.js';\r\nimport type { GeminiService } from '../../services/gemini.service.js';\r\nimport pLimit from 'p-limit';\r\n\r\nexport class AnthropicHandler implements EnhancementHandler {\r\n private readonly config: AnthropicContextualConfig;\r\n private readonly gemini: GeminiService;\r\n private readonly limit: ReturnType<typeof pLimit>;\r\n private readonly skipTypes: Set<string>;\r\n\r\n constructor(config: AnthropicContextualConfig, gemini: GeminiService) {\r\n this.config = config;\r\n this.gemini = gemini;\r\n this.limit = pLimit(config.concurrencyLimit ?? DEFAULTS.concurrencyLimit);\r\n this.skipTypes = new Set(config.skipChunkTypes ?? DEFAULTS.skipChunkTypes);\r\n }\r\n\r\n shouldSkip(chunkType: string): boolean {\r\n return this.skipTypes.has(chunkType);\r\n }\r\n\r\n async generateContext(chunk: ChunkData, doc: DocumentContext): Promise<string> {\r\n // Skip if chunk type is in skip list\r\n if (this.shouldSkip(chunk.chunkType)) {\r\n return '';\r\n }\r\n\r\n switch (this.config.strategy) {\r\n case 'none':\r\n return '';\r\n\r\n case 'simple':\r\n return this.generateSimpleContext(chunk, doc);\r\n\r\n case 'llm':\r\n return this.limit(() => this.generateLLMContext(chunk, doc));\r\n\r\n default:\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Simple template-based context generation (free)\r\n */\r\n private generateSimpleContext(chunk: ChunkData, doc: DocumentContext): string {\r\n const template = this.config.template ?? DEFAULTS.template;\r\n\r\n return template\r\n .replace('{documentType}', doc.documentType ?? 'Document')\r\n .replace('{chunkType}', chunk.chunkType)\r\n .replace('{page}', String(chunk.page))\r\n .replace('{parentHeading}', chunk.parentHeading ?? '');\r\n }\r\n\r\n /**\r\n * LLM-based context generation (best quality, ~$0.005/chunk)\r\n */\r\n private async generateLLMContext(chunk: ChunkData, doc: DocumentContext): Promise<string> {\r\n const prompt = this.config.contextPrompt ?? DEFAULTS.contextPrompt;\r\n\r\n const fullPrompt = `${prompt}\r\n\r\n<document_info>\r\nDosya: ${doc.filename}\r\nTip: ${doc.documentType ?? 'Bilinmiyor'}\r\nToplam Sayfa: ${doc.pageCount}\r\n</document_info>\r\n\r\n${doc.fullDocumentText ? `<full_document>\r\n${doc.fullDocumentText.slice(0, 15000)}\r\n</full_document>\r\n\r\n` : ''}<chunk_to_contextualize>\r\n${chunk.content}\r\n</chunk_to_contextualize>\r\n\r\nBu chunk'ın belgede nerede olduğunu ve ne hakkında olduğunu 1-2 cümle ile Türkçe açıkla:`;\r\n\r\n try {\r\n // If we have a cached PDF URI, use it for full document context (Anthropic-style)\r\n if (doc.fileUri) {\r\n const chunkPrompt = `Bu chunk'ın belgede nerede olduğunu ve ne hakkında olduğunu 1-2 cümle ile Türkçe açıkla:\r\n\r\n<chunk>\r\n${chunk.content}\r\n</chunk>`;\r\n const result = await this.gemini.generateWithPdfUri(doc.fileUri, chunkPrompt);\r\n return result.text;\r\n }\r\n\r\n // Otherwise, generate without full document context\r\n const result = await this.gemini.generateSimple(fullPrompt);\r\n return result;\r\n } catch (error) {\r\n // On error, fall back to simple context\r\n console.warn('LLM context generation failed, using simple context:', error);\r\n return this.generateSimpleContext(chunk, doc);\r\n }\r\n }\r\n}\r\n","/**\r\n * Enhancement Registry\r\n * \r\n * Factory for creating enhancement handlers based on configuration.\r\n */\r\n\r\nimport type {\r\n RagEnhancementConfig,\r\n EnhancementHandler,\r\n ChunkData,\r\n DocumentContext\r\n} from '../types/rag-enhancement.types.js';\r\nimport type { ResolvedConfig } from '../types/config.types.js';\r\nimport type { GeminiService } from '../services/gemini.service.js';\r\nimport { NoOpHandler } from './no-op.handler.js';\r\nimport { AnthropicHandler } from './anthropic/anthropic.handler.js';\r\n\r\n/**\r\n * Create an enhancement handler based on configuration\r\n */\r\nexport function createEnhancementHandler(\r\n config: RagEnhancementConfig | undefined,\r\n resolvedConfig: ResolvedConfig,\r\n gemini: GeminiService\r\n): EnhancementHandler {\r\n if (!config || config.approach === 'none') {\r\n return new NoOpHandler();\r\n }\r\n\r\n switch (config.approach) {\r\n case 'anthropic_contextual':\r\n return new AnthropicHandler(config, gemini);\r\n\r\n case 'google_grounding':\r\n // Future implementation\r\n throw new Error('Google Grounding is not yet implemented');\r\n\r\n case 'custom':\r\n return new CustomHandler(config.handler, config.skipChunkTypes);\r\n\r\n default:\r\n throw new Error(`Unknown RAG enhancement approach: ${(config as RagEnhancementConfig).approach}`);\r\n }\r\n}\r\n\r\n/**\r\n * Custom handler wrapper\r\n */\r\nclass CustomHandler implements EnhancementHandler {\r\n constructor(\r\n private readonly handler: (ctx: { chunk: ChunkData; doc: DocumentContext }) => Promise<string>,\r\n private readonly skipChunkTypes?: string[]\r\n ) { }\r\n\r\n shouldSkip(chunkType: string): boolean {\r\n return this.skipChunkTypes?.includes(chunkType) ?? false;\r\n }\r\n\r\n async generateContext(chunk: ChunkData, doc: DocumentContext): Promise<string> {\r\n if (this.shouldSkip(chunk.chunkType)) {\r\n return '';\r\n }\r\n return this.handler({ chunk, doc });\r\n }\r\n}\r\n","\r\nimport type { PrismaClientLike } from '../types/config.types.js';\r\nimport type { ResolvedConfig } from '../types/config.types.js';\r\nimport type {\r\n IngestOptions,\r\n IngestResult,\r\n BatchStatus,\r\n BatchResult,\r\n} from '../types/ingestion.types.js';\r\nimport type { CreateChunkInput, TokenUsage } from '../types/chunk.types.js';\r\nimport { BatchStatusEnum, DocumentStatusEnum } from '../types/enums.js';\r\nimport { DocumentRepository } from '../database/repositories/document.repository.js';\r\nimport { BatchRepository } from '../database/repositories/batch.repository.js';\r\nimport { ChunkRepository } from '../database/repositories/chunk.repository.js';\r\nimport { PromptConfigRepository } from '../database/repositories/prompt-config.repository.js';\r\nimport { GeminiService } from '../services/gemini.service.js';\r\nimport { PDFProcessor } from '../services/pdf.processor.js';\r\nimport { withRetry, getRetryOptions } from '../utils/retry.js';\r\nimport type { Logger } from '../utils/logger.js';\r\nimport { RateLimiter } from '../utils/rate-limiter.js';\r\nimport {\r\n buildExtractionPrompt,\r\n DEFAULT_DOCUMENT_INSTRUCTIONS\r\n} from '../config/templates.js';\r\nimport {\r\n parseSections,\r\n hasValidSections,\r\n parseFallbackContent,\r\n cleanForSearch\r\n} from '../utils/chunk-parser.js';\r\nimport { createEnhancementHandler } from '../enhancements/enhancement-registry.js';\r\nimport type { EnhancementHandler, DocumentContext, ChunkData } from '../types/rag-enhancement.types.js';\r\n\r\n/**\r\n * Ingestion engine for processing documents\r\n * \r\n * Uses structured template system for consistent output format\r\n * with <!-- SECTION --> markers for reliable parsing.\r\n */\r\nexport class IngestionEngine {\r\n private readonly config: ResolvedConfig;\r\n private readonly prisma: PrismaClientLike;\r\n private readonly gemini: GeminiService;\r\n private readonly pdfProcessor: PDFProcessor;\r\n private readonly documentRepo: DocumentRepository;\r\n private readonly batchRepo: BatchRepository;\r\n private readonly chunkRepo: ChunkRepository;\r\n private readonly promptConfigRepo: PromptConfigRepository;\r\n private readonly logger: Logger;\r\n private readonly enhancementHandler: EnhancementHandler;\r\n\r\n constructor(\r\n config: ResolvedConfig,\r\n rateLimiter: RateLimiter,\r\n logger: Logger\r\n ) {\r\n this.config = config;\r\n this.prisma = config.prisma;\r\n this.gemini = new GeminiService(config, rateLimiter, logger);\r\n this.pdfProcessor = new PDFProcessor(logger);\r\n this.documentRepo = new DocumentRepository(this.prisma);\r\n this.batchRepo = new BatchRepository(this.prisma);\r\n this.chunkRepo = new ChunkRepository(this.prisma);\r\n this.promptConfigRepo = new PromptConfigRepository(this.prisma);\r\n this.logger = logger;\r\n this.enhancementHandler = createEnhancementHandler(\r\n config.ragEnhancement,\r\n config,\r\n this.gemini\r\n );\r\n }\r\n\r\n /**\r\n * Ingest a document\r\n */\r\n async ingest(options: IngestOptions): Promise<IngestResult> {\r\n const startTime = Date.now();\r\n\r\n this.logger.info('Starting ingestion', {\r\n documentType: options.documentType,\r\n });\r\n\r\n // Load PDF\r\n const { buffer, metadata } = await this.pdfProcessor.load(options.file);\r\n\r\n // Upload PDF to Gemini Files API (cache for batch processing and context generation)\r\n const fileUri = await this.gemini.uploadPdfBuffer(buffer, metadata.filename);\r\n\r\n // Check for existing document (by hash + experimentId)\r\n if (options.skipExisting) {\r\n const existing = await this.documentRepo.getByHashAndExperiment(\r\n metadata.fileHash,\r\n options.experimentId\r\n );\r\n if (existing) {\r\n this.logger.info('Document already exists for this experiment, skipping', {\r\n documentId: existing.id,\r\n experimentId: options.experimentId,\r\n });\r\n return {\r\n documentId: existing.id,\r\n status: existing.status as IngestResult['status'],\r\n chunkCount: 0,\r\n batchCount: existing.progress.totalBatches,\r\n failedBatchCount: existing.progress.failedBatches,\r\n tokenUsage: existing.tokenUsage ?? { input: 0, output: 0, total: 0 },\r\n processingMs: 0,\r\n batches: [],\r\n warnings: ['Document already exists for this experiment, skipped processing'],\r\n };\r\n }\r\n }\r\n\r\n // Get document-specific instructions\r\n let documentInstructions: string[] = [];\r\n let exampleFormats: Record<string, string> | undefined;\r\n let promptConfigId: string | undefined = options.promptConfigId;\r\n\r\n if (!promptConfigId && options.documentType) {\r\n const promptConfig = await this.promptConfigRepo.getDefault(options.documentType);\r\n if (promptConfig) {\r\n promptConfigId = promptConfig.id;\r\n // Parse instructions from systemPrompt (stored as newline-separated)\r\n documentInstructions = promptConfig.systemPrompt\r\n .split('\\n')\r\n .map(line => line.trim())\r\n .filter(line => line.length > 0);\r\n }\r\n }\r\n\r\n // Use custom prompt or default instructions\r\n if (options.customPrompt) {\r\n documentInstructions = options.customPrompt\r\n .split('\\n')\r\n .map(line => line.trim())\r\n .filter(line => line.length > 0);\r\n } else if (documentInstructions.length === 0) {\r\n documentInstructions = DEFAULT_DOCUMENT_INSTRUCTIONS\r\n .split('\\n')\r\n .map(line => line.replace(/^-\\s*/, '').trim())\r\n .filter(line => line.length > 0);\r\n }\r\n\r\n // Create batches\r\n const batchSpecs = this.pdfProcessor.createBatches(\r\n metadata.pageCount,\r\n this.config.batchConfig.pagesPerBatch\r\n );\r\n\r\n // Create document record with experiment info\r\n const documentId = await this.documentRepo.create({\r\n filename: options.filename ?? metadata.filename,\r\n fileHash: metadata.fileHash,\r\n fileSize: metadata.fileSize,\r\n pageCount: metadata.pageCount,\r\n documentType: options.documentType,\r\n promptConfigId,\r\n totalBatches: batchSpecs.length,\r\n experimentId: options.experimentId,\r\n modelName: this.config.model,\r\n modelConfig: {\r\n temperature: this.config.generationConfig?.temperature,\r\n maxOutputTokens: this.config.generationConfig?.maxOutputTokens,\r\n },\r\n });\r\n\r\n // Create batch records\r\n await this.batchRepo.createMany(\r\n batchSpecs.map(spec => ({\r\n documentId,\r\n batchIndex: spec.batchIndex,\r\n pageStart: spec.pageStart,\r\n pageEnd: spec.pageEnd,\r\n }))\r\n );\r\n\r\n // Update document status\r\n await this.documentRepo.update(documentId, {\r\n status: DocumentStatusEnum.PROCESSING,\r\n });\r\n\r\n // Process batches with concurrency control\r\n const batchResults = await this.processBatchesConcurrently(\r\n documentId,\r\n // buffer removed\r\n documentInstructions,\r\n exampleFormats,\r\n promptConfigId ?? 'default',\r\n fileUri,\r\n metadata.filename,\r\n options.onProgress\r\n );\r\n\r\n // Calculate totals\r\n const totalTokenUsage: TokenUsage = {\r\n input: 0,\r\n output: 0,\r\n total: 0,\r\n };\r\n let totalChunks = 0;\r\n let failedCount = 0;\r\n\r\n for (const result of batchResults) {\r\n totalTokenUsage.input += result.tokenUsage.input;\r\n totalTokenUsage.output += result.tokenUsage.output;\r\n totalTokenUsage.total += result.tokenUsage.total;\r\n totalChunks += result.chunksCreated;\r\n if (result.status === BatchStatusEnum.FAILED) {\r\n failedCount++;\r\n }\r\n }\r\n\r\n const processingMs = Date.now() - startTime;\r\n\r\n // Mark document as completed\r\n await this.documentRepo.markCompleted(documentId, totalTokenUsage, processingMs);\r\n\r\n const status = failedCount > 0 ? DocumentStatusEnum.PARTIAL : DocumentStatusEnum.COMPLETED;\r\n\r\n this.logger.info('Ingestion completed', {\r\n documentId,\r\n status,\r\n chunkCount: totalChunks,\r\n batchCount: batchSpecs.length,\r\n failedBatchCount: failedCount,\r\n processingMs,\r\n });\r\n\r\n return {\r\n documentId,\r\n status: status as IngestResult['status'],\r\n chunkCount: totalChunks,\r\n batchCount: batchSpecs.length,\r\n failedBatchCount: failedCount,\r\n tokenUsage: totalTokenUsage,\r\n processingMs,\r\n batches: batchResults,\r\n warnings: failedCount > 0 ? [`${failedCount} batch(es) failed to process`] : undefined,\r\n };\r\n }\r\n\r\n /**\r\n * Process batches with concurrency control\r\n */\r\n private async processBatchesConcurrently(\r\n documentId: string,\r\n // pdfBuffer removed - using Files API fileUri instead\r\n documentInstructions: string[],\r\n exampleFormats: Record<string, string> | undefined,\r\n promptConfigId: string,\r\n fileUri: string, // [NEW] Files API URI\r\n filename: string,\r\n onProgress?: (status: BatchStatus) => void\r\n ): Promise<BatchResult[]> {\r\n const batches = await this.batchRepo.getByDocumentId(documentId);\r\n const results: BatchResult[] = [];\r\n const { maxConcurrency } = this.config.batchConfig;\r\n\r\n // Process in chunks of maxConcurrency\r\n for (let i = 0; i < batches.length; i += maxConcurrency) {\r\n const currentBatch = batches.slice(i, i + maxConcurrency);\r\n\r\n const batchPromises = currentBatch.map(batch =>\r\n this.processSingleBatch(\r\n batch,\r\n // pdfBuffer removed\r\n documentInstructions,\r\n exampleFormats,\r\n promptConfigId,\r\n fileUri,\r\n filename,\r\n documentId,\r\n batches.length,\r\n onProgress\r\n )\r\n );\r\n\r\n const batchResults = await Promise.all(batchPromises);\r\n results.push(...batchResults);\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Process a single batch with retry logic\r\n */\r\n private async processSingleBatch(\r\n batch: { id: string; batchIndex: number; pageStart: number; pageEnd: number },\r\n // pdfBuffer removed\r\n documentInstructions: string[],\r\n exampleFormats: Record<string, string> | undefined,\r\n promptConfigId: string,\r\n fileUri: string,\r\n filename: string,\r\n documentId: string,\r\n totalBatches: number,\r\n onProgress?: (status: BatchStatus) => void\r\n ): Promise<BatchResult> {\r\n const startTime = Date.now();\r\n\r\n // Report progress\r\n onProgress?.({\r\n current: batch.batchIndex + 1,\r\n total: totalBatches,\r\n status: BatchStatusEnum.PROCESSING,\r\n pageRange: { start: batch.pageStart, end: batch.pageEnd },\r\n });\r\n\r\n await this.batchRepo.markProcessing(batch.id);\r\n\r\n const retryOptions = getRetryOptions(this.config.batchConfig);\r\n let retryCount = 0;\r\n\r\n try {\r\n const result = await withRetry(\r\n async () => {\r\n // Build structured extraction prompt using template\r\n const prompt = buildExtractionPrompt(\r\n documentInstructions,\r\n exampleFormats,\r\n batch.pageStart,\r\n batch.pageEnd\r\n );\r\n\r\n // Use Files API with cached PDF URI (optimized)\r\n const fullPrompt = `${prompt}\r\n \r\n IMPORTANT: You have the FULL document. Restrict your extraction STRICTLY to pages ${batch.pageStart} to ${batch.pageEnd}. Do not extract content from other pages.`;\r\n\r\n const response = await this.gemini.generateWithPdfUri(\r\n fileUri,\r\n fullPrompt,\r\n {\r\n temperature: this.config.generationConfig?.temperature,\r\n maxOutputTokens: this.config.generationConfig?.maxOutputTokens,\r\n }\r\n );\r\n\r\n return response;\r\n },\r\n {\r\n ...retryOptions,\r\n onRetry: (attempt, error) => {\r\n retryCount = attempt;\r\n this.logger.warn('Batch retry', {\r\n batchId: batch.id,\r\n attempt,\r\n error: error.message,\r\n });\r\n onProgress?.({\r\n current: batch.batchIndex + 1,\r\n total: totalBatches,\r\n status: BatchStatusEnum.RETRYING,\r\n pageRange: { start: batch.pageStart, end: batch.pageEnd },\r\n retryCount: attempt,\r\n });\r\n },\r\n }\r\n );\r\n\r\n // Parse AI output using structured section parser\r\n const chunks = this.parseContentToChunks(\r\n result.text,\r\n promptConfigId,\r\n documentId,\r\n batch.pageStart,\r\n batch.pageEnd\r\n );\r\n\r\n // RAG Enhancement: Generate context for each chunk (Anthropic-style)\r\n const docContext: DocumentContext = {\r\n documentType: undefined, // Inferred from processing\r\n filename: filename,\r\n pageCount: batch.pageEnd, // Approximate from batch\r\n fileUri: fileUri, // Pass the Files API URI for context generation\r\n };\r\n\r\n // Generate context and create enriched content\r\n for (const chunk of chunks) {\r\n const chunkData: ChunkData = {\r\n content: chunk.displayContent,\r\n searchContent: chunk.searchContent,\r\n displayContent: chunk.displayContent,\r\n chunkType: chunk.chunkType,\r\n page: chunk.sourcePageStart,\r\n parentHeading: undefined, // Could be extracted from metadata\r\n };\r\n\r\n // Generate context using enhancement handler\r\n const context = await this.enhancementHandler.generateContext(chunkData, docContext);\r\n\r\n // Store context and create enriched content\r\n if (context) {\r\n (chunk as any).contextText = context;\r\n const enriched = `${context} ${chunk.searchContent}`;\r\n (chunk as any).enrichedContent = enriched;\r\n\r\n // [Context-RAG Update]\r\n // Update searchContent to include context for proper hybrid search indexing.\r\n // This aligns with Anthropic's Contextual Retrieval architecture where \r\n // the BM25 (Keyword) index is built from the \"Context + Chunk\" content.\r\n chunk.searchContent = enriched;\r\n }\r\n }\r\n\r\n // Generate embeddings using enrichedContent if available, otherwise searchContent\r\n const textsToEmbed = chunks.map(c =>\r\n (c as any).enrichedContent ?? c.searchContent\r\n );\r\n const embeddings = await this.gemini.embedBatch(textsToEmbed);\r\n\r\n await this.chunkRepo.createMany(\r\n chunks,\r\n embeddings.map(e => e.embedding)\r\n );\r\n\r\n // Mark batch as completed\r\n const processingMs = Date.now() - startTime;\r\n await this.batchRepo.markCompleted(batch.id, result.tokenUsage, processingMs);\r\n await this.documentRepo.incrementCompleted(documentId);\r\n\r\n onProgress?.({\r\n current: batch.batchIndex + 1,\r\n total: totalBatches,\r\n status: BatchStatusEnum.COMPLETED,\r\n pageRange: { start: batch.pageStart, end: batch.pageEnd },\r\n });\r\n\r\n return {\r\n batchIndex: batch.batchIndex,\r\n status: BatchStatusEnum.COMPLETED,\r\n chunksCreated: chunks.length,\r\n tokenUsage: result.tokenUsage,\r\n processingMs,\r\n retryCount,\r\n };\r\n } catch (error) {\r\n const errorMessage = (error as Error).message;\r\n\r\n await this.batchRepo.markFailed(batch.id, errorMessage);\r\n await this.documentRepo.incrementFailed(documentId);\r\n\r\n onProgress?.({\r\n current: batch.batchIndex + 1,\r\n total: totalBatches,\r\n status: BatchStatusEnum.FAILED,\r\n pageRange: { start: batch.pageStart, end: batch.pageEnd },\r\n error: errorMessage,\r\n });\r\n\r\n this.logger.error('Batch failed', {\r\n batchId: batch.id,\r\n error: errorMessage,\r\n });\r\n\r\n return {\r\n batchIndex: batch.batchIndex,\r\n status: BatchStatusEnum.FAILED,\r\n chunksCreated: 0,\r\n tokenUsage: { input: 0, output: 0, total: 0 },\r\n processingMs: Date.now() - startTime,\r\n retryCount,\r\n error: errorMessage,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Parse extracted content into chunks\r\n * Uses structured <!-- SECTION --> markers when available,\r\n * falls back to legacy parsing for compatibility.\r\n */\r\n private parseContentToChunks(\r\n content: string,\r\n promptConfigId: string,\r\n documentId: string,\r\n pageStart: number,\r\n pageEnd: number\r\n ): CreateChunkInput[] {\r\n const chunks: CreateChunkInput[] = [];\r\n\r\n // Try structured section parsing first\r\n if (hasValidSections(content)) {\r\n const sections = parseSections(content);\r\n\r\n this.logger.debug('Using structured section parser', {\r\n sectionCount: sections.length,\r\n });\r\n\r\n for (const section of sections) {\r\n if (section.content.length < 10) continue;\r\n\r\n chunks.push({\r\n promptConfigId,\r\n documentId,\r\n chunkIndex: section.index,\r\n chunkType: section.type,\r\n searchContent: cleanForSearch(section.content),\r\n displayContent: section.content,\r\n sourcePageStart: section.page,\r\n sourcePageEnd: section.page,\r\n confidenceScore: section.confidence,\r\n metadata: {\r\n type: section.type,\r\n pageRange: { start: section.page, end: section.page },\r\n confidence: {\r\n score: section.confidence,\r\n category: section.confidence >= 0.8 ? 'HIGH' :\r\n section.confidence >= 0.5 ? 'MEDIUM' : 'LOW'\r\n },\r\n parsedWithStructuredMarkers: true,\r\n },\r\n });\r\n }\r\n\r\n return chunks;\r\n }\r\n\r\n // Fallback to legacy parsing\r\n this.logger.debug('Using fallback parser (no structured markers found)');\r\n\r\n const sections = parseFallbackContent(content, pageStart, pageEnd);\r\n\r\n for (const section of sections) {\r\n if (section.content.length < 10) continue;\r\n\r\n chunks.push({\r\n promptConfigId,\r\n documentId,\r\n chunkIndex: section.index,\r\n chunkType: section.type,\r\n searchContent: cleanForSearch(section.content),\r\n displayContent: section.content,\r\n sourcePageStart: pageStart,\r\n sourcePageEnd: pageEnd,\r\n confidenceScore: section.confidence,\r\n metadata: {\r\n type: section.type,\r\n pageRange: { start: pageStart, end: pageEnd },\r\n confidence: { score: section.confidence, category: 'MEDIUM' },\r\n parsedWithStructuredMarkers: false,\r\n },\r\n });\r\n }\r\n\r\n return chunks;\r\n }\r\n}\r\n","import type { ResolvedConfig } from '../types/config.types.js';\r\nimport type {\r\n SearchOptions,\r\n SearchResult,\r\n SearchResponse,\r\n SearchFilters,\r\n} from '../types/search.types.js';\r\nimport { ChunkRepository } from '../database/repositories/chunk.repository.js';\r\nimport { GeminiService } from '../services/gemini.service.js';\r\nimport type { Logger } from '../utils/logger.js';\r\nimport { RateLimiter } from '../utils/rate-limiter.js';\r\nimport { SearchModeEnum } from '../types/enums.js';\r\n\r\n/**\r\n * Retrieval engine for semantic and hybrid search\r\n */\r\nexport class RetrievalEngine {\r\n private readonly chunkRepo: ChunkRepository;\r\n private readonly gemini: GeminiService;\r\n private readonly logger: Logger;\r\n\r\n constructor(\r\n config: ResolvedConfig,\r\n rateLimiter: RateLimiter,\r\n logger: Logger\r\n ) {\r\n this.chunkRepo = new ChunkRepository(config.prisma);\r\n this.gemini = new GeminiService(config, rateLimiter, logger);\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Search for relevant content\r\n * Note: HEADING chunks are excluded by default. Use filters.chunkTypes to include them.\r\n */\r\n async search(options: SearchOptions): Promise<SearchResult[]> {\r\n const startTime = Date.now();\r\n const mode = options.mode ?? SearchModeEnum.HYBRID;\r\n const limit = options.limit ?? 10;\r\n\r\n // Apply default filter to exclude HEADING chunks unless explicitly included\r\n const filters: SearchFilters = {\r\n ...options.filters,\r\n };\r\n\r\n // If chunkTypes not specified, exclude HEADING by default\r\n if (!filters.chunkTypes) {\r\n filters.chunkTypes = ['TEXT', 'TABLE', 'LIST', 'CODE', 'QUOTE', 'IMAGE_REF', 'QUESTION', 'MIXED'];\r\n }\r\n\r\n this.logger.debug('Starting search', {\r\n query: options.query.substring(0, 50),\r\n mode,\r\n limit,\r\n });\r\n\r\n let results: SearchResult[];\r\n\r\n switch (mode) {\r\n case SearchModeEnum.SEMANTIC:\r\n results = await this.semanticSearch(options.query, limit, filters, options.minScore);\r\n break;\r\n case SearchModeEnum.KEYWORD:\r\n results = await this.keywordSearch(options.query, limit, filters);\r\n break;\r\n case SearchModeEnum.HYBRID:\r\n default:\r\n results = await this.hybridSearch(options.query, limit, filters, options.minScore);\r\n break;\r\n }\r\n\r\n // Apply type boosting if specified\r\n if (options.typeBoost) {\r\n results = this.applyTypeBoost(results, options.typeBoost);\r\n }\r\n\r\n // Add explanations if requested\r\n if (options.includeExplanation) {\r\n results = results.map(r => ({\r\n ...r,\r\n explanation: {\r\n matchType: mode === SearchModeEnum.HYBRID ? 'both' : mode === SearchModeEnum.SEMANTIC ? 'semantic' : 'keyword',\r\n rawScores: {\r\n semantic: r.score,\r\n },\r\n },\r\n }));\r\n }\r\n\r\n this.logger.debug('Search completed', {\r\n resultCount: results.length,\r\n processingTimeMs: Date.now() - startTime,\r\n });\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Search with full metadata response\r\n */\r\n async searchWithMetadata(options: SearchOptions): Promise<SearchResponse> {\r\n const startTime = Date.now();\r\n const results = await this.search(options);\r\n\r\n return {\r\n results,\r\n metadata: {\r\n totalFound: results.length,\r\n processingTimeMs: Date.now() - startTime,\r\n searchMode: options.mode ?? SearchModeEnum.HYBRID,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Semantic search using vector similarity\r\n */\r\n private async semanticSearch(\r\n query: string,\r\n limit: number,\r\n filters?: SearchFilters,\r\n minScore?: number\r\n ): Promise<SearchResult[]> {\r\n // Generate query embedding with RETRIEVAL_QUERY task type\r\n const { embedding } = await this.gemini.embedQuery(query);\r\n\r\n // Search in vector database\r\n const results = await this.chunkRepo.searchSemantic(\r\n embedding,\r\n limit,\r\n filters,\r\n minScore\r\n );\r\n\r\n return results.map(r => ({\r\n chunk: r.chunk,\r\n score: r.similarity,\r\n }));\r\n }\r\n\r\n /**\r\n * Keyword-based search using full-text search\r\n */\r\n private async keywordSearch(\r\n query: string,\r\n limit: number,\r\n filters?: SearchFilters\r\n ): Promise<SearchResult[]> {\r\n const results = await this.chunkRepo.searchKeyword(query, limit, filters);\r\n\r\n return results.map(r => ({\r\n chunk: r.chunk,\r\n score: r.similarity,\r\n }));\r\n }\r\n\r\n /**\r\n * Hybrid search combining semantic and keyword\r\n */\r\n private async hybridSearch(\r\n query: string,\r\n limit: number,\r\n filters?: SearchFilters,\r\n minScore?: number\r\n ): Promise<SearchResult[]> {\r\n // Run both searches in parallel\r\n const [semanticResults, keywordResults] = await Promise.all([\r\n this.semanticSearch(query, limit * 2, filters, minScore),\r\n this.keywordSearch(query, limit * 2, filters),\r\n ]);\r\n\r\n // Combine and deduplicate results\r\n const combinedMap = new Map<string, SearchResult>();\r\n\r\n // Add semantic results with weight 0.7\r\n for (const result of semanticResults) {\r\n combinedMap.set(result.chunk.id, {\r\n ...result,\r\n score: result.score * 0.7,\r\n });\r\n }\r\n\r\n // Add keyword results with weight 0.3, combining scores if already exists\r\n for (const result of keywordResults) {\r\n const existing = combinedMap.get(result.chunk.id);\r\n if (existing) {\r\n existing.score += result.score * 0.3;\r\n } else {\r\n combinedMap.set(result.chunk.id, {\r\n ...result,\r\n score: result.score * 0.3,\r\n });\r\n }\r\n }\r\n\r\n // Sort by combined score and limit\r\n const combined = Array.from(combinedMap.values())\r\n .sort((a, b) => b.score - a.score)\r\n .slice(0, limit);\r\n\r\n return combined;\r\n }\r\n\r\n /**\r\n * Apply type-based boosting to results\r\n */\r\n private applyTypeBoost(\r\n results: SearchResult[],\r\n typeBoost: Partial<Record<string, number>>\r\n ): SearchResult[] {\r\n return results\r\n .map(result => {\r\n const boost = typeBoost[result.chunk.chunkType] ?? 1;\r\n return {\r\n ...result,\r\n score: result.score * boost,\r\n explanation: result.explanation\r\n ? {\r\n ...result.explanation,\r\n intentBoost: boost !== 1,\r\n boostReason: boost !== 1 ? `Type boost for ${result.chunk.chunkType}: ${boost}x` : undefined,\r\n }\r\n : undefined,\r\n };\r\n })\r\n .sort((a, b) => b.score - a.score);\r\n }\r\n}\r\n","import type { ResolvedConfig } from '../types/config.types.js';\r\nimport type {\r\n DiscoveryResult,\r\n DiscoveryOptions,\r\n DetectedElement,\r\n} from '../types/discovery.types.js';\r\nimport type { ChunkStrategy } from '../types/chunk.types.js';\r\nimport { GeminiService } from '../services/gemini.service.js';\r\nimport { PDFProcessor } from '../services/pdf.processor.js';\r\nimport type { Logger } from '../utils/logger.js';\r\nimport { RateLimiter } from '../utils/rate-limiter.js';\r\nimport { generateCorrelationId } from '../utils/index.js';\r\nimport { DEFAULT_CHUNK_STRATEGY } from '../types/prompt.types.js';\r\nimport { buildDiscoveryPrompt } from '../config/templates.js';\r\n\r\n/**\r\n * Discovery session storage\r\n */\r\ninterface DiscoverySession {\r\n id: string;\r\n result: DiscoveryResult;\r\n fileBuffer: Buffer;\r\n createdAt: Date;\r\n expiresAt: Date;\r\n}\r\n\r\n/**\r\n * Parsed discovery response from AI\r\n */\r\ninterface DiscoveryAIResponse {\r\n documentType: string;\r\n documentTypeName: string;\r\n language?: string;\r\n complexity?: 'low' | 'medium' | 'high';\r\n detectedElements: DetectedElement[];\r\n specialInstructions: string[];\r\n exampleFormats?: Record<string, string>;\r\n chunkStrategy?: Partial<ChunkStrategy>;\r\n confidence: number;\r\n reasoning: string;\r\n}\r\n\r\n/**\r\n * Discovery engine for automatic prompt generation\r\n * \r\n * Uses structured template system to analyze documents and generate\r\n * document-specific extraction instructions.\r\n */\r\nexport class DiscoveryEngine {\r\n private readonly gemini: GeminiService;\r\n private readonly pdfProcessor: PDFProcessor;\r\n private readonly logger: Logger;\r\n private readonly sessions: Map<string, DiscoverySession> = new Map();\r\n\r\n constructor(\r\n config: ResolvedConfig,\r\n rateLimiter: RateLimiter,\r\n logger: Logger\r\n ) {\r\n this.gemini = new GeminiService(config, rateLimiter, logger);\r\n this.pdfProcessor = new PDFProcessor(logger);\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Analyze a document and generate processing strategy\r\n */\r\n async discover(options: DiscoveryOptions): Promise<DiscoveryResult> {\r\n const correlationId = generateCorrelationId();\r\n\r\n this.logger.info('Starting document discovery', { correlationId });\r\n\r\n // Load PDF\r\n const { buffer, metadata } = await this.pdfProcessor.load(options.file);\r\n\r\n // Upload PDF to Gemini Files API (cache for analysis)\r\n const fileUri = await this.gemini.uploadPdfBuffer(buffer, metadata.filename);\r\n\r\n // Build discovery prompt from template\r\n const prompt = buildDiscoveryPrompt(options.documentTypeHint);\r\n\r\n // Call Gemini with full document via Files API\r\n const response = await this.gemini.generateWithPdfUri(fileUri, prompt);\r\n\r\n // Parse response\r\n let analysisResult: DiscoveryAIResponse;\r\n\r\n try {\r\n // Extract JSON from response (handle markdown code blocks)\r\n let jsonStr = response.text;\r\n const jsonMatch = jsonStr.match(/```json\\s*([\\s\\S]*?)\\s*```/) || jsonStr.match(/```\\s*([\\s\\S]*?)\\s*```/);\r\n if (jsonMatch?.[1]) {\r\n jsonStr = jsonMatch[1];\r\n }\r\n analysisResult = JSON.parse(jsonStr) as DiscoveryAIResponse;\r\n\r\n // Validate required fields\r\n if (!analysisResult.documentType) {\r\n throw new Error('Missing documentType in response');\r\n }\r\n if (!Array.isArray(analysisResult.specialInstructions)) {\r\n // Fallback: convert old suggestedPrompt to instructions if present\r\n analysisResult.specialInstructions = this.getDefaultInstructions();\r\n }\r\n } catch (parseError) {\r\n this.logger.warn('Failed to parse discovery response as JSON, using defaults', {\r\n error: (parseError as Error).message,\r\n });\r\n\r\n // Use defaults\r\n analysisResult = {\r\n documentType: options.documentTypeHint ?? 'General',\r\n documentTypeName: options.documentTypeHint ?? 'General Document',\r\n detectedElements: [],\r\n specialInstructions: this.getDefaultInstructions(),\r\n chunkStrategy: DEFAULT_CHUNK_STRATEGY,\r\n confidence: 0.5,\r\n reasoning: 'Failed to parse AI response, using default configuration',\r\n };\r\n }\r\n\r\n // Build discovery result\r\n const discoveryResult: DiscoveryResult = {\r\n id: correlationId,\r\n documentType: analysisResult.documentType,\r\n documentTypeName: analysisResult.documentTypeName,\r\n detectedElements: analysisResult.detectedElements ?? [],\r\n specialInstructions: analysisResult.specialInstructions,\r\n exampleFormats: analysisResult.exampleFormats,\r\n suggestedChunkStrategy: {\r\n ...DEFAULT_CHUNK_STRATEGY,\r\n ...analysisResult.chunkStrategy,\r\n },\r\n confidence: analysisResult.confidence ?? 0.5,\r\n reasoning: analysisResult.reasoning ?? '',\r\n pageCount: metadata.pageCount,\r\n fileHash: metadata.fileHash,\r\n createdAt: new Date(),\r\n expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours\r\n };\r\n\r\n // Store session for later approval\r\n this.sessions.set(correlationId, {\r\n id: correlationId,\r\n result: discoveryResult,\r\n fileBuffer: buffer,\r\n createdAt: new Date(),\r\n expiresAt: discoveryResult.expiresAt,\r\n });\r\n\r\n // Clean up old sessions\r\n this.cleanupSessions();\r\n\r\n this.logger.info('Discovery completed', {\r\n correlationId,\r\n documentType: discoveryResult.documentType,\r\n confidence: discoveryResult.confidence,\r\n instructionCount: discoveryResult.specialInstructions.length,\r\n });\r\n\r\n return discoveryResult;\r\n }\r\n\r\n /**\r\n * Get stored discovery session\r\n */\r\n getSession(id: string): DiscoverySession | undefined {\r\n const session = this.sessions.get(id);\r\n if (session && session.expiresAt > new Date()) {\r\n return session;\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Remove a session after approval\r\n */\r\n removeSession(id: string): void {\r\n this.sessions.delete(id);\r\n }\r\n\r\n /**\r\n * Clean up expired sessions\r\n */\r\n private cleanupSessions(): void {\r\n const now = new Date();\r\n for (const [id, session] of this.sessions) {\r\n if (session.expiresAt <= now) {\r\n this.sessions.delete(id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get default extraction instructions\r\n */\r\n private getDefaultInstructions(): string[] {\r\n return [\r\n 'Extract all text content preserving structure',\r\n 'Convert tables to Markdown table format',\r\n 'Convert lists to Markdown list format',\r\n 'Preserve headings with appropriate # levels',\r\n 'Note any images with [IMAGE: description]',\r\n 'Maintain the logical flow of content',\r\n ];\r\n }\r\n}\r\n","import type {\r\n ContextRAGConfig,\r\n ResolvedConfig,\r\n} from './types/config.types.js';\r\nimport type {\r\n DiscoveryResult,\r\n DiscoveryOptions,\r\n ApproveStrategyOptions,\r\n} from './types/discovery.types.js';\r\nimport type {\r\n IngestOptions,\r\n IngestResult,\r\n DocumentStatus,\r\n RetryOptions,\r\n} from './types/ingestion.types.js';\r\nimport type {\r\n SearchOptions,\r\n SearchResult,\r\n SearchResponse,\r\n} from './types/search.types.js';\r\nimport type {\r\n PromptConfig,\r\n CreatePromptConfig,\r\n UpdatePromptConfig,\r\n PromptConfigFilters,\r\n} from './types/prompt.types.js';\r\n\r\nimport {\r\n configSchema,\r\n DEFAULT_BATCH_CONFIG,\r\n DEFAULT_CHUNK_CONFIG,\r\n DEFAULT_RATE_LIMIT_CONFIG,\r\n DEFAULT_GENERATION_CONFIG,\r\n DEFAULT_LOG_CONFIG,\r\n} from './types/config.types.js';\r\nimport { ConfigurationError, NotFoundError } from './errors/index.js';\r\nimport { createLogger, RateLimiter } from './utils/index.js';\r\nimport type { Logger } from './utils/logger.js';\r\nimport {\r\n PromptConfigRepository,\r\n DocumentRepository,\r\n ChunkRepository,\r\n} from './database/index.js';\r\nimport {\r\n checkDatabaseConnection,\r\n checkPgVectorExtension,\r\n getDatabaseStats,\r\n} from './database/utils.js';\r\nimport { IngestionEngine } from './engines/ingestion.engine.js';\r\nimport { RetrievalEngine } from './engines/retrieval.engine.js';\r\nimport { DiscoveryEngine } from './engines/discovery.engine.js';\r\n\r\n/**\r\n * Main Context-RAG engine class\r\n *\r\n * @example\r\n * ```typescript\r\n * import { ContextRAG } from 'context-rag';\r\n * import { PrismaClient } from '@prisma/client';\r\n *\r\n * const prisma = new PrismaClient();\r\n * const rag = new ContextRAG({\r\n * prisma,\r\n * geminiApiKey: process.env.GEMINI_API_KEY!,\r\n * });\r\n *\r\n * // Ingest a document\r\n * const result = await rag.ingest({ file: pdfBuffer });\r\n *\r\n * // Search\r\n * const results = await rag.search({ query: 'your query' });\r\n * ```\r\n */\r\nexport class ContextRAG {\r\n private readonly config: ResolvedConfig;\r\n private readonly logger: Logger;\r\n private readonly rateLimiter: RateLimiter;\r\n\r\n // Engines\r\n private readonly ingestionEngine: IngestionEngine;\r\n private readonly retrievalEngine: RetrievalEngine;\r\n private readonly discoveryEngine: DiscoveryEngine;\r\n\r\n // Repositories\r\n private readonly promptConfigRepo: PromptConfigRepository;\r\n private readonly documentRepo: DocumentRepository;\r\n private readonly chunkRepo: ChunkRepository;\r\n\r\n constructor(userConfig: ContextRAGConfig) {\r\n // Validate config\r\n const validation = configSchema.safeParse(userConfig);\r\n if (!validation.success) {\r\n throw new ConfigurationError('Invalid configuration', {\r\n errors: validation.error.errors,\r\n });\r\n }\r\n\r\n // Resolve config with defaults\r\n this.config = this.resolveConfig(userConfig);\r\n\r\n // Initialize logger\r\n this.logger = createLogger(this.config.logging);\r\n\r\n // Initialize rate limiter\r\n this.rateLimiter = new RateLimiter(this.config.rateLimitConfig);\r\n\r\n // Initialize repositories\r\n this.promptConfigRepo = new PromptConfigRepository(this.config.prisma);\r\n this.documentRepo = new DocumentRepository(this.config.prisma);\r\n this.chunkRepo = new ChunkRepository(this.config.prisma);\r\n\r\n // Initialize engines\r\n this.ingestionEngine = new IngestionEngine(this.config, this.rateLimiter, this.logger);\r\n this.retrievalEngine = new RetrievalEngine(this.config, this.rateLimiter, this.logger);\r\n this.discoveryEngine = new DiscoveryEngine(this.config, this.rateLimiter, this.logger);\r\n\r\n this.logger.info('Context-RAG initialized', {\r\n model: this.config.model,\r\n batchConfig: this.config.batchConfig,\r\n });\r\n }\r\n\r\n /**\r\n * Resolve user config with defaults\r\n */\r\n private resolveConfig(userConfig: ContextRAGConfig): ResolvedConfig {\r\n return {\r\n prisma: userConfig.prisma,\r\n geminiApiKey: userConfig.geminiApiKey,\r\n model: userConfig.model ?? 'gemini-1.5-pro',\r\n embeddingModel: userConfig.embeddingModel ?? 'text-embedding-004',\r\n generationConfig: {\r\n ...DEFAULT_GENERATION_CONFIG,\r\n ...userConfig.generationConfig,\r\n },\r\n batchConfig: {\r\n ...DEFAULT_BATCH_CONFIG,\r\n ...userConfig.batchConfig,\r\n },\r\n chunkConfig: {\r\n ...DEFAULT_CHUNK_CONFIG,\r\n ...userConfig.chunkConfig,\r\n },\r\n rateLimitConfig: {\r\n ...DEFAULT_RATE_LIMIT_CONFIG,\r\n ...userConfig.rateLimitConfig,\r\n },\r\n logging: {\r\n ...DEFAULT_LOG_CONFIG,\r\n ...userConfig.logging,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Get the resolved configuration\r\n */\r\n getConfig(): ResolvedConfig {\r\n return this.config;\r\n }\r\n\r\n // ============================================\r\n // DISCOVERY METHODS\r\n // ============================================\r\n\r\n /**\r\n * Analyze a document and get AI-suggested processing strategy\r\n */\r\n async discover(options: DiscoveryOptions): Promise<DiscoveryResult> {\r\n return this.discoveryEngine.discover(options);\r\n }\r\n\r\n /**\r\n * Approve a discovery strategy and create a prompt config\r\n */\r\n async approveStrategy(\r\n strategyId: string,\r\n overrides?: ApproveStrategyOptions\r\n ): Promise<PromptConfig> {\r\n const session = this.discoveryEngine.getSession(strategyId);\r\n\r\n if (!session) {\r\n throw new NotFoundError('Discovery session', strategyId);\r\n }\r\n\r\n const result = session.result;\r\n\r\n // Build system prompt from specialInstructions or use override/deprecated suggestedPrompt\r\n const systemPrompt = overrides?.systemPrompt\r\n ?? result.suggestedPrompt\r\n ?? result.specialInstructions.join('\\n');\r\n\r\n // Create prompt config with optional overrides\r\n const promptConfig = await this.promptConfigRepo.create({\r\n documentType: overrides?.documentType ?? result.documentType,\r\n name: overrides?.name ?? result.documentTypeName,\r\n systemPrompt,\r\n chunkStrategy: {\r\n ...result.suggestedChunkStrategy,\r\n ...overrides?.chunkStrategy,\r\n },\r\n setAsDefault: true,\r\n changeLog: overrides?.changeLog ?? `Auto-generated from discovery (confidence: ${result.confidence})`,\r\n });\r\n\r\n // Remove session after successful approval\r\n this.discoveryEngine.removeSession(strategyId);\r\n\r\n this.logger.info('Strategy approved', {\r\n strategyId,\r\n promptConfigId: promptConfig.id,\r\n });\r\n\r\n return promptConfig;\r\n }\r\n\r\n // ============================================\r\n // PROMPT CONFIG METHODS\r\n // ============================================\r\n\r\n /**\r\n * Create a custom prompt configuration\r\n */\r\n async createPromptConfig(config: CreatePromptConfig): Promise<PromptConfig> {\r\n return this.promptConfigRepo.create(config);\r\n }\r\n\r\n /**\r\n * Get prompt configurations\r\n */\r\n async getPromptConfigs(filters?: PromptConfigFilters): Promise<PromptConfig[]> {\r\n return this.promptConfigRepo.getMany(filters);\r\n }\r\n\r\n /**\r\n * Update a prompt configuration (creates new version)\r\n */\r\n async updatePromptConfig(\r\n id: string,\r\n updates: UpdatePromptConfig\r\n ): Promise<PromptConfig> {\r\n const existing = await this.promptConfigRepo.getById(id);\r\n\r\n // Create new version with updates\r\n return this.promptConfigRepo.create({\r\n documentType: existing.documentType,\r\n name: updates.name ?? existing.name,\r\n systemPrompt: updates.systemPrompt ?? existing.systemPrompt,\r\n chunkStrategy: {\r\n ...existing.chunkStrategy,\r\n ...updates.chunkStrategy,\r\n },\r\n setAsDefault: true,\r\n changeLog: updates.changeLog ?? `Updated from version ${existing.version}`,\r\n });\r\n }\r\n\r\n /**\r\n * Activate a specific prompt config version\r\n */\r\n async activatePromptConfig(id: string): Promise<void> {\r\n return this.promptConfigRepo.activate(id);\r\n }\r\n\r\n // ============================================\r\n // INGESTION METHODS\r\n // ============================================\r\n\r\n /**\r\n * Ingest a document into the RAG system\r\n */\r\n async ingest(options: IngestOptions): Promise<IngestResult> {\r\n return this.ingestionEngine.ingest(options);\r\n }\r\n\r\n /**\r\n * Get the status of a document processing job\r\n */\r\n async getDocumentStatus(documentId: string): Promise<DocumentStatus> {\r\n return this.documentRepo.getById(documentId);\r\n }\r\n\r\n /**\r\n * Retry failed batches for a document\r\n */\r\n async retryFailedBatches(\r\n documentId: string,\r\n _options?: RetryOptions\r\n ): Promise<IngestResult> {\r\n // Get the document to get the file info\r\n const doc = await this.documentRepo.getById(documentId);\r\n\r\n // For now, throw an error - full implementation would require storing the file\r\n throw new Error(\r\n `Retry not yet fully implemented. Document ${doc.id} has ${doc.progress.failedBatches} failed batches.`\r\n );\r\n }\r\n\r\n // ============================================\r\n // SEARCH METHODS\r\n // ============================================\r\n\r\n /**\r\n * Search for relevant content\r\n */\r\n async search(options: SearchOptions): Promise<SearchResult[]> {\r\n return this.retrievalEngine.search(options);\r\n }\r\n\r\n /**\r\n * Search with full metadata response\r\n */\r\n async searchWithMetadata(options: SearchOptions): Promise<SearchResponse> {\r\n return this.retrievalEngine.searchWithMetadata(options);\r\n }\r\n\r\n // ============================================\r\n // ADMIN METHODS\r\n // ============================================\r\n\r\n /**\r\n * Delete a document and all its chunks\r\n */\r\n async deleteDocument(documentId: string): Promise<void> {\r\n this.logger.info('Deleting document', { documentId });\r\n\r\n // Delete chunks first\r\n await this.chunkRepo.deleteByDocumentId(documentId);\r\n\r\n // Delete document (will cascade delete batches)\r\n await this.documentRepo.delete(documentId);\r\n }\r\n\r\n /**\r\n * Get system statistics\r\n */\r\n async getStats(): Promise<{\r\n totalDocuments: number;\r\n totalChunks: number;\r\n promptConfigs: number;\r\n storageBytes: number;\r\n }> {\r\n const stats = await getDatabaseStats(this.config.prisma);\r\n return {\r\n totalDocuments: stats.documents,\r\n totalChunks: stats.chunks,\r\n promptConfigs: stats.promptConfigs,\r\n storageBytes: stats.totalStorageBytes,\r\n };\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<{\r\n status: 'healthy' | 'degraded' | 'unhealthy';\r\n database: boolean;\r\n pgvector: boolean;\r\n }> {\r\n const database = await checkDatabaseConnection(this.config.prisma);\r\n let pgvector = false;\r\n\r\n if (database) {\r\n try {\r\n pgvector = await checkPgVectorExtension(this.config.prisma);\r\n } catch {\r\n pgvector = false;\r\n }\r\n }\r\n\r\n let status: 'healthy' | 'degraded' | 'unhealthy';\r\n if (database && pgvector) {\r\n status = 'healthy';\r\n } else if (database) {\r\n status = 'degraded';\r\n } else {\r\n status = 'unhealthy';\r\n }\r\n\r\n return { status, database, pgvector };\r\n }\r\n}\r\n"]}
|