@eclipse-lyra/extension-rag-system 0.0.0

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.
Files changed (62) hide show
  1. package/dist/api.d.ts +9 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +90 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/chunkers/chunker-interface.d.ts +21 -0
  6. package/dist/chunkers/chunker-interface.d.ts.map +1 -0
  7. package/dist/chunkers/document-chunker.d.ts +12 -0
  8. package/dist/chunkers/document-chunker.d.ts.map +1 -0
  9. package/dist/chunkers/fallback-chunker.d.ts +10 -0
  10. package/dist/chunkers/fallback-chunker.d.ts.map +1 -0
  11. package/dist/chunkers/langchain-chunker.d.ts +12 -0
  12. package/dist/chunkers/langchain-chunker.d.ts.map +1 -0
  13. package/dist/document-index-service.d.ts +102 -0
  14. package/dist/document-index-service.d.ts.map +1 -0
  15. package/dist/embedding-service.d.ts +18 -0
  16. package/dist/embedding-service.d.ts.map +1 -0
  17. package/dist/extractors/document-extractor-interface.d.ts +26 -0
  18. package/dist/extractors/document-extractor-interface.d.ts.map +1 -0
  19. package/dist/extractors/document-extractor.d.ts +13 -0
  20. package/dist/extractors/document-extractor.d.ts.map +1 -0
  21. package/dist/extractors/llm-ocr-extractor.d.ts +16 -0
  22. package/dist/extractors/llm-ocr-extractor.d.ts.map +1 -0
  23. package/dist/extractors/pdfjs-extractor.d.ts +7 -0
  24. package/dist/extractors/pdfjs-extractor.d.ts.map +1 -0
  25. package/dist/i18n.json.d.ts +13 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +22 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/rag-integration-DO7-zvk2.js +191 -0
  31. package/dist/rag-integration-DO7-zvk2.js.map +1 -0
  32. package/dist/rag-integration.d.ts +6 -0
  33. package/dist/rag-integration.d.ts.map +1 -0
  34. package/dist/rag-service-BKBGCuO-.js +1872 -0
  35. package/dist/rag-service-BKBGCuO-.js.map +1 -0
  36. package/dist/rag-service.d.ts +25 -0
  37. package/dist/rag-service.d.ts.map +1 -0
  38. package/dist/rag-system-extension-DfD6H8Vr.js +1142 -0
  39. package/dist/rag-system-extension-DfD6H8Vr.js.map +1 -0
  40. package/dist/rag-system-extension.d.ts +2 -0
  41. package/dist/rag-system-extension.d.ts.map +1 -0
  42. package/dist/rag-system-manager.d.ts +41 -0
  43. package/dist/rag-system-manager.d.ts.map +1 -0
  44. package/dist/rxdb-loader.d.ts +9 -0
  45. package/dist/rxdb-loader.d.ts.map +1 -0
  46. package/dist/services/rag-result-formatter.d.ts +23 -0
  47. package/dist/services/rag-result-formatter.d.ts.map +1 -0
  48. package/dist/services/relevance-calculator.d.ts +7 -0
  49. package/dist/services/relevance-calculator.d.ts.map +1 -0
  50. package/dist/utils/constants.d.ts +35 -0
  51. package/dist/utils/constants.d.ts.map +1 -0
  52. package/dist/utils/context-scopes.d.ts +39 -0
  53. package/dist/utils/context-scopes.d.ts.map +1 -0
  54. package/dist/utils/query-utils.d.ts +7 -0
  55. package/dist/utils/query-utils.d.ts.map +1 -0
  56. package/dist/utils/snippet-extractor.d.ts +22 -0
  57. package/dist/utils/snippet-extractor.d.ts.map +1 -0
  58. package/dist/utils/workspace-utils.d.ts +8 -0
  59. package/dist/utils/workspace-utils.d.ts.map +1 -0
  60. package/dist/vector-utils.d.ts +28 -0
  61. package/dist/vector-utils.d.ts.map +1 -0
  62. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-service-BKBGCuO-.js","sources":["../src/embedding-service.ts","../src/utils/constants.ts","../src/vector-utils.ts","../src/chunkers/fallback-chunker.ts","../src/chunkers/langchain-chunker.ts","../src/chunkers/document-chunker.ts","../src/extractors/pdfjs-extractor.ts","../src/extractors/llm-ocr-extractor.ts","../src/extractors/document-extractor.ts","../src/rxdb-loader.ts","../src/document-index-service.ts","../src/utils/workspace-utils.ts","../src/utils/query-utils.ts","../src/utils/snippet-extractor.ts","../src/services/relevance-calculator.ts","../src/services/rag-result-formatter.ts","../src/rag-service.ts"],"sourcesContent":["import { createLogger } from '@eclipse-lyra/core';\nimport { inBrowserMLService, MLModel, MLTask, type FeatureExtractionPipeline } from '@eclipse-lyra/extension-in-browser-ml/api';\n\nconst logger = createLogger('EmbeddingService');\n\nexport interface EmbeddingOptions {\n pooling?: 'mean' | 'cls' | 'none';\n normalize?: boolean;\n}\n\nclass EmbeddingService {\n private pipePromise?: Promise<FeatureExtractionPipeline>;\n private modelName = MLModel.FEATURE_EXTRACTION;\n private readonly EMBEDDING_DIMENSION = 384;\n private readonly DEFAULT_OPTIONS: EmbeddingOptions = {\n pooling: 'mean',\n normalize: true\n };\n\n async initialize(): Promise<void> {\n if (this.pipePromise) {\n try {\n await this.pipePromise;\n return;\n } catch (error) {\n logger.warn('Previous initialization failed, retrying...');\n this.pipePromise = undefined;\n }\n }\n\n logger.info(`Initializing embedding service with model: ${this.modelName}`);\n \n try {\n this.pipePromise = inBrowserMLService.getPipeline(\n MLTask.FEATURE_EXTRACTION,\n this.modelName,\n { quantized: false }\n ) as Promise<FeatureExtractionPipeline>;\n await this.pipePromise;\n logger.info('Embedding service initialized successfully');\n } catch (error: any) {\n const errorMessage = error?.message || String(error);\n const errorDetails = error ? JSON.stringify(error) : '';\n logger.error(`Failed to initialize embedding service: ${errorMessage}${errorDetails ? ` - ${errorDetails}` : ''}`);\n this.pipePromise = undefined;\n throw new Error(`Embedding service initialization failed: ${errorMessage}`);\n }\n }\n\n async generateEmbedding(\n text: string,\n options: EmbeddingOptions = {}\n ): Promise<number[]> {\n if (!this.pipePromise) {\n await this.initialize();\n }\n\n const pipe = await this.pipePromise!;\n const opts = { ...this.DEFAULT_OPTIONS, ...options };\n \n try {\n const output = await pipe(text, {\n pooling: opts.pooling as 'mean' | 'cls' | 'none' | undefined,\n normalize: opts.normalize,\n });\n\n const embedding = Array.from(output.data) as number[];\n \n if (embedding.length !== this.EMBEDDING_DIMENSION) {\n logger.warn(`Unexpected embedding dimension: ${embedding.length}, expected ${this.EMBEDDING_DIMENSION}`);\n }\n\n return embedding;\n } catch (error) {\n logger.error(`Failed to generate embedding: ${error}`);\n throw error;\n }\n }\n\n async generateEmbeddings(\n texts: string[],\n options: EmbeddingOptions = {}\n ): Promise<number[][]> {\n const embeddings: number[][] = [];\n \n for (const text of texts) {\n const embedding = await this.generateEmbedding(text, options);\n embeddings.push(embedding);\n }\n \n return embeddings;\n }\n\n getEmbeddingDimension(): number {\n return this.EMBEDDING_DIMENSION;\n }\n\n getModelName(): string {\n return this.modelName;\n }\n}\n\nexport const embeddingService = new EmbeddingService();\n\n","export const SNIPPET_LENGTHS = {\n DEFAULT: 400,\n PREVIEW: 500,\n LONG_PREVIEW: 1000,\n CONTEXT: 150,\n} as const;\n\nexport const RELEVANCE_WEIGHTS = {\n FILE_NAME_MATCH: 10,\n FILE_PATH_MATCH: 5,\n CONTENT_MATCH: 1,\n FILE_NAME_EXACT: 20,\n FILE_PATH_EXACT: 10,\n EXACT_PHRASE: 5,\n TERM_COVERAGE: 15,\n} as const;\n\nexport const SEARCH_CONFIG = {\n DEFAULT_LIMIT: 5,\n MAX_LIMIT: 20,\n DEFAULT_MIN_RELEVANCE: 0,\n QUERY_TERM_MIN_LENGTH: 2,\n} as const;\n\nexport const VECTOR_SEARCH_CONFIG = {\n DEFAULT_INDEX_DISTANCE: 2.0,\n DEFAULT_DOCS_PER_INDEX_SIDE: 100,\n DEFAULT_LIMIT: 10,\n SAMPLE_VECTOR_COUNT: 5,\n} as const;\n\nexport const INDEX_FIELD_NAMES = [\n 'idx0', 'idx1', 'idx2', 'idx3', 'idx4'\n] as const;\n\nexport type IndexFieldName = typeof INDEX_FIELD_NAMES[number];\n\nexport const CONTENT_PREVIEW_LENGTHS = {\n SHORT: 200,\n MEDIUM: 500,\n LONG: 1000,\n} as const;\n\n","import { INDEX_FIELD_NAMES, VECTOR_SEARCH_CONFIG } from './utils/constants';\n\nexport interface VectorEmbedding {\n id: string;\n documentId: string;\n chunkIndex?: number;\n chunkStartOffset?: number;\n chunkEndOffset?: number;\n embedding: number[];\n idx0: number;\n idx1: number;\n idx2: number;\n idx3: number;\n idx4: number;\n}\n\nexport type IndexValues = {\n [K in typeof INDEX_FIELD_NAMES[number]]: number;\n};\n\nexport interface SampleVector {\n vector: number[];\n idx: number;\n}\n\nexport function euclideanDistance(vec1: number[], vec2: number[]): number {\n if (vec1.length !== vec2.length) {\n throw new Error(`Vector dimensions must match: ${vec1.length} vs ${vec2.length}`);\n }\n\n let sum = 0;\n for (let i = 0; i < vec1.length; i++) {\n const diff = vec1[i] - vec2[i];\n sum += diff * diff;\n }\n return Math.sqrt(sum);\n}\n\nexport function generateSampleVectors(\n count: number,\n dimension: number,\n existingEmbeddings?: number[][]\n): SampleVector[] {\n const samples: SampleVector[] = [];\n\n if (existingEmbeddings && existingEmbeddings.length > 0) {\n for (let i = 0; i < count; i++) {\n if (i < existingEmbeddings.length) {\n samples.push({\n vector: existingEmbeddings[i],\n idx: i\n });\n } else {\n const vector: number[] = [];\n for (let j = 0; j < dimension; j++) {\n vector.push(Math.random() * 2 - 1);\n }\n samples.push({\n vector,\n idx: i\n });\n }\n }\n } else {\n for (let i = 0; i < count; i++) {\n const vector: number[] = [];\n for (let j = 0; j < dimension; j++) {\n vector.push(Math.random() * 2 - 1);\n }\n samples.push({\n vector,\n idx: i\n });\n }\n }\n\n return samples;\n}\n\nexport function calculateIndexValues(\n embedding: number[],\n sampleVectors: SampleVector[]\n): IndexValues {\n if (sampleVectors.length !== INDEX_FIELD_NAMES.length) {\n throw new Error(\n `Sample vectors count (${sampleVectors.length}) must match index field count (${INDEX_FIELD_NAMES.length})`\n );\n }\n\n const result = {} as IndexValues;\n for (let i = 0; i < INDEX_FIELD_NAMES.length; i++) {\n result[INDEX_FIELD_NAMES[i]] = euclideanDistance(embedding, sampleVectors[i].vector);\n }\n return result;\n}\n\nexport function getIndexValueArray(indexValues: IndexValues): number[] {\n return INDEX_FIELD_NAMES.map(name => indexValues[name]);\n}\n\nexport function createIndexValuesFromArray(values: number[]): IndexValues {\n if (values.length !== INDEX_FIELD_NAMES.length) {\n throw new Error(\n `Values array length (${values.length}) must match index field count (${INDEX_FIELD_NAMES.length})`\n );\n }\n const result = {} as IndexValues;\n for (let i = 0; i < INDEX_FIELD_NAMES.length; i++) {\n result[INDEX_FIELD_NAMES[i]] = values[i];\n }\n return result;\n}\n\nexport function cosineSimilarity(vec1: number[], vec2: number[]): number {\n if (vec1.length !== vec2.length) {\n throw new Error(`Vector dimensions must match: ${vec1.length} vs ${vec2.length}`);\n }\n\n let dotProduct = 0;\n let norm1 = 0;\n let norm2 = 0;\n\n for (let i = 0; i < vec1.length; i++) {\n dotProduct += vec1[i] * vec2[i];\n norm1 += vec1[i] * vec1[i];\n norm2 += vec2[i] * vec2[i];\n }\n\n const denominator = Math.sqrt(norm1) * Math.sqrt(norm2);\n if (denominator === 0) {\n return 0;\n }\n\n return dotProduct / denominator;\n}\n\n","import { SNIPPET_LENGTHS } from '../utils/constants';\nimport type { DocumentChunk, ChunkingOptions, IDocumentChunker } from './chunker-interface';\n\nconst DEFAULT_CHUNK_SIZE = 500;\nconst DEFAULT_CHUNK_OVERLAP = 50;\nconst DEFAULT_MIN_CHUNK_SIZE = 100;\n\nexport class FallbackChunker implements IDocumentChunker {\n private readonly chunkSize: number;\n private readonly chunkOverlap: number;\n private readonly minChunkSize: number;\n\n constructor(options: ChunkingOptions = {}) {\n this.chunkSize = options.chunkSize ?? DEFAULT_CHUNK_SIZE;\n this.chunkOverlap = options.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;\n this.minChunkSize = options.minChunkSize ?? DEFAULT_MIN_CHUNK_SIZE;\n }\n\n chunkDocument(\n documentId: string,\n content: string,\n fileName: string\n ): DocumentChunk[] {\n if (content.length <= this.chunkSize) {\n const text = `${fileName} ${content}`;\n return [{\n id: `${documentId}:chunk:0`,\n documentId,\n chunkIndex: 0,\n text,\n startOffset: 0,\n endOffset: content.length\n }];\n }\n\n const chunks: DocumentChunk[] = [];\n const step = this.chunkSize - this.chunkOverlap;\n let offset = 0;\n let chunkIndex = 0;\n\n while (offset < content.length) {\n const endOffset = Math.min(offset + this.chunkSize, content.length);\n const chunkText = content.substring(offset, endOffset);\n \n if (chunkText.trim().length < this.minChunkSize && chunks.length > 0) {\n break;\n }\n\n const text = chunkIndex === 0 \n ? `${fileName} ${chunkText}`\n : chunkText;\n\n chunks.push({\n id: `${documentId}:chunk:${chunkIndex}`,\n documentId,\n chunkIndex,\n text,\n startOffset: offset,\n endOffset\n });\n\n offset += step;\n chunkIndex++;\n }\n\n return chunks;\n }\n\n getChunkContext(chunk: DocumentChunk, allChunks: DocumentChunk[]): string {\n const prevChunk = chunk.chunkIndex > 0 \n ? allChunks[chunk.chunkIndex - 1] \n : null;\n const nextChunk = chunk.chunkIndex < allChunks.length - 1\n ? allChunks[chunk.chunkIndex + 1]\n : null;\n\n let context = '';\n if (prevChunk) {\n context += `[Previous: ${prevChunk.text.substring(Math.max(0, prevChunk.text.length - SNIPPET_LENGTHS.CONTEXT))}]\\n\\n`;\n }\n context += chunk.text;\n if (nextChunk) {\n context += `\\n\\n[Next: ${nextChunk.text.substring(0, SNIPPET_LENGTHS.CONTEXT)}]`;\n }\n\n return context;\n }\n}\n\n","import { createLogger } from '@eclipse-lyra/core';\nimport { SNIPPET_LENGTHS } from '../utils/constants';\nimport type { DocumentChunk, ChunkingOptions, IDocumentChunker } from './chunker-interface';\ntype RecursiveCharacterTextSplitter = import('@langchain/textsplitters').RecursiveCharacterTextSplitter;\n\nconst logger = createLogger('LangChainChunker');\n\nconst DEFAULT_CHUNK_SIZE = 500; // words\nconst DEFAULT_CHUNK_OVERLAP = 75; // words (15% of chunk size for better context preservation)\n\nfunction countWords(text: string): number {\n if (!text || text.trim().length === 0) {\n return 0;\n }\n return text.trim().split(/\\s+/).filter(word => word.length > 0).length;\n}\n\nexport class LangChainChunker implements IDocumentChunker {\n private textSplitter: RecursiveCharacterTextSplitter | null = null;\n private readonly chunkSize: number;\n private readonly chunkOverlap: number;\n\n constructor(options: ChunkingOptions = {}) {\n this.chunkSize = options.chunkSize ?? DEFAULT_CHUNK_SIZE;\n this.chunkOverlap = options.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;\n }\n\n private async getTextSplitter(): Promise<RecursiveCharacterTextSplitter> {\n if (!this.textSplitter) {\n const { RecursiveCharacterTextSplitter } = await import('@langchain/textsplitters');\n this.textSplitter = new RecursiveCharacterTextSplitter({\n chunkSize: this.chunkSize,\n chunkOverlap: this.chunkOverlap,\n lengthFunction: countWords,\n separators: [\n '\\n\\n',\n '\\n',\n '. ',\n '! ',\n '? ',\n ' ',\n ],\n keepSeparator: false,\n });\n }\n return this.textSplitter;\n }\n\n async chunkDocument(\n documentId: string,\n content: string,\n fileName: string\n ): Promise<DocumentChunk[]> {\n try {\n const splitter = await this.getTextSplitter();\n const chunks = await splitter.splitText(content);\n \n const documentChunks: DocumentChunk[] = [];\n let currentOffset = 0;\n\n for (let index = 0; index < chunks.length; index++) {\n const chunkText = chunks[index];\n \n let startOffset: number;\n \n if (index === 0) {\n const foundPos = content.indexOf(chunkText);\n startOffset = foundPos !== -1 ? foundPos : 0;\n currentOffset = startOffset;\n } else {\n const prevChunk = documentChunks[index - 1];\n \n const overlapBuffer = Math.max(this.chunkOverlap * 10, chunkText.length);\n const searchStart = Math.max(0, prevChunk.endOffset - overlapBuffer);\n const searchEnd = Math.min(content.length, prevChunk.endOffset + chunkText.length);\n \n const searchWindow = content.substring(searchStart, searchEnd);\n const relativePos = searchWindow.indexOf(chunkText);\n \n if (relativePos !== -1) {\n const candidateOffset = searchStart + relativePos;\n if (candidateOffset >= prevChunk.startOffset && candidateOffset < prevChunk.endOffset + chunkText.length) {\n startOffset = candidateOffset;\n } else {\n startOffset = prevChunk.endOffset;\n }\n } else {\n startOffset = prevChunk.endOffset;\n }\n currentOffset = startOffset;\n }\n \n const endOffset = Math.min(startOffset + chunkText.length, content.length);\n const text = index === 0 ? `${fileName} ${chunkText}` : chunkText;\n \n documentChunks.push({\n id: `${documentId}:chunk:${index}`,\n documentId,\n chunkIndex: index,\n text,\n startOffset,\n endOffset\n });\n }\n\n this.validateNoWordSplitting(documentChunks, content, documentId);\n\n logger.debug(`Document ${documentId} split into ${documentChunks.length} chunks using LangChain`);\n return documentChunks;\n } catch (error) {\n logger.warn(`LangChain chunking failed for ${documentId}, falling back to simple chunking: ${error}`);\n throw error;\n }\n }\n\n private validateNoWordSplitting(chunks: DocumentChunk[], originalContent: string, documentId: string): void {\n for (let i = 0; i < chunks.length - 1; i++) {\n const currentChunk = chunks[i];\n const nextChunk = chunks[i + 1];\n \n if (currentChunk.endOffset < originalContent.length && nextChunk.startOffset > currentChunk.endOffset) {\n const gap = originalContent.substring(currentChunk.endOffset, nextChunk.startOffset);\n const gapTrimmed = gap.trim();\n \n if (gapTrimmed.length > 0 && !/^\\s+$/.test(gap)) {\n const beforeChar = originalContent[currentChunk.endOffset - 1];\n const afterChar = originalContent[nextChunk.startOffset];\n \n if (beforeChar && afterChar && \n /[a-zA-Z0-9]/.test(beforeChar) && /[a-zA-Z0-9]/.test(afterChar)) {\n logger.warn(`Potential word split detected in document ${documentId} between chunks ${i} and ${i + 1}`);\n }\n }\n }\n }\n }\n\n getChunkContext(chunk: DocumentChunk, allChunks: DocumentChunk[]): string {\n const prevChunk = chunk.chunkIndex > 0 \n ? allChunks[chunk.chunkIndex - 1] \n : null;\n const nextChunk = chunk.chunkIndex < allChunks.length - 1\n ? allChunks[chunk.chunkIndex + 1]\n : null;\n\n let context = '';\n if (prevChunk) {\n context += `[Previous: ${prevChunk.text.substring(Math.max(0, prevChunk.text.length - SNIPPET_LENGTHS.CONTEXT))}]\\n\\n`;\n }\n context += chunk.text;\n if (nextChunk) {\n context += `\\n\\n[Next: ${nextChunk.text.substring(0, SNIPPET_LENGTHS.CONTEXT)}]`;\n }\n\n return context;\n }\n}\n\n","export type { DocumentChunk, ChunkingOptions, IDocumentChunker } from './chunker-interface';\nexport { FallbackChunker } from './fallback-chunker';\nexport { LangChainChunker } from './langchain-chunker';\n\nimport { LangChainChunker } from './langchain-chunker';\nimport { FallbackChunker } from './fallback-chunker';\nimport { createLogger } from '@eclipse-lyra/core';\nimport type { ChunkingOptions, IDocumentChunker, DocumentChunk } from './chunker-interface';\n\nconst logger = createLogger('DocumentChunker');\n\nexport class DocumentChunker implements IDocumentChunker {\n private chunker: IDocumentChunker;\n\n constructor(options: ChunkingOptions = {}) {\n try {\n this.chunker = new LangChainChunker(options);\n logger.debug('Using LangChain chunker');\n } catch (error) {\n logger.warn(`Failed to initialize LangChain chunker, using fallback: ${error}`);\n this.chunker = new FallbackChunker(options);\n }\n }\n\n async chunkDocument(documentId: string, content: string, fileName: string) {\n try {\n const result = this.chunker.chunkDocument(documentId, content, fileName);\n return await Promise.resolve(result);\n } catch (error) {\n logger.warn(`Primary chunker failed, falling back: ${error}`);\n const fallback = new FallbackChunker();\n return fallback.chunkDocument(documentId, content, fileName);\n }\n }\n\n getChunkContext(chunk: any, allChunks: any[]) {\n return this.chunker.getChunkContext(chunk, allChunks);\n }\n}\n\nexport const defaultChunker = new DocumentChunker();\n","import type { File } from '@eclipse-lyra/core';\nimport { createLogger } from '@eclipse-lyra/core';\nimport type { IDocumentExtractor, DocumentExtractionOptions } from './document-extractor-interface';\n\nconst logger = createLogger('PDFJSExtractor');\n\nexport class PDFJSExtractor implements IDocumentExtractor {\n canExtract(fileType: string): boolean {\n return fileType.toLowerCase() === 'pdf';\n }\n\n async extractText(file: File, options: DocumentExtractionOptions = {}): Promise<string> {\n try {\n const pdfjsLib = await import('pdfjs-dist');\n \n // Configure PDF.js worker\n if (!pdfjsLib.GlobalWorkerOptions.workerSrc) {\n // Use unpkg CDN - more reliable than cdnjs and matches the installed version\n pdfjsLib.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjsLib.version}/build/pdf.worker.min.mjs`;\n }\n \n const pdfBlob = await file.getContents({ blob: true }) as Blob;\n const arrayBuffer = await pdfBlob.arrayBuffer();\n \n const loadingTask = pdfjsLib.getDocument({ \n data: arrayBuffer,\n useSystemFonts: true\n });\n const pdf = await loadingTask.promise;\n \n const numPages = pdf.numPages;\n const textParts: string[] = [];\n const includePageNumbers = options.includePageNumbers !== false;\n const pageSeparator = options.pageSeparator || '\\n\\n';\n \n for (let pageNum = 1; pageNum <= numPages; pageNum++) {\n const page = await pdf.getPage(pageNum);\n const textContent = await page.getTextContent();\n \n const pageText = textContent.items\n .map((item: any) => item.str)\n .join(' ');\n \n if (pageText.trim()) {\n if (includePageNumbers) {\n textParts.push(`[Page ${pageNum}]\\n${pageText}`);\n } else {\n textParts.push(pageText);\n }\n }\n }\n \n const extractedText = textParts.join(pageSeparator);\n \n if (!extractedText || extractedText.trim().length === 0) {\n throw new Error('PDF appears to contain no extractable text (may be image-based or scanned)');\n }\n \n logger.debug(`Extracted ${numPages} pages from PDF: ${file.getName()}`);\n return extractedText;\n } catch (error) {\n logger.warn(`Failed to extract text from PDF ${file.getName()}: ${error}`);\n throw new Error(`PDF text extraction failed: ${error}`);\n }\n }\n}\n\n","import type { File } from '@eclipse-lyra/core';\nimport { createLogger } from '@eclipse-lyra/core';\nimport type { IDocumentExtractor, DocumentExtractionOptions } from './document-extractor-interface';\nimport { aiService, type ChatProvider } from '@eclipse-lyra/extension-ai-system/api';\n\nconst logger = createLogger('LLMOCRExtractor');\n\n/**\n * LLM-based OCR extractor for document files using Mistral OCR.\n * \n * This extractor uses Mistral OCR API to perform OCR on document files,\n * particularly useful for scanned documents or image-based files\n * that cannot be processed by standard text extraction methods.\n */\nexport class LLMOCRExtractor implements IDocumentExtractor {\n canExtract(fileType: string): boolean {\n return ['pdf', 'png', 'jpg', 'jpeg', 'tiff', 'tif'].includes(fileType.toLowerCase());\n }\n\n async extractText(file: File, options: DocumentExtractionOptions = {}): Promise<string> {\n const fileName = file.getName();\n const fileType = options?.fileType || fileName.split('.').pop()?.toLowerCase() || 'pdf';\n \n const providers = await aiService.getProviders();\n const ocrProvider = providers.find(p => {\n const endpoint = p.parameters?.['ocrApiEndpoint'] as string | undefined;\n return endpoint && p.name.toLowerCase().includes('mistral');\n });\n const ocrEndpoint = ocrProvider?.parameters?.['ocrApiEndpoint'] as string | undefined;\n\n if (!ocrProvider || !ocrEndpoint) {\n throw new Error('Mistral OCR provider not configured. Please add ocrApiEndpoint to the provider parameters in AI settings.');\n }\n\n try {\n const fileBlob = await file.getContents({ blob: true }) as Blob;\n const base64Content = await this.blobToBase64(fileBlob);\n const mimeType = this.getMimeType(fileType);\n \n const response = await fetch(ocrEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${ocrProvider.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n model: (ocrProvider.parameters?.['ocrModel'] as string | undefined) || ocrProvider.model || 'mistral-ocr-latest',\n document: {\n type: 'document_url',\n document_url: `data:${mimeType};base64,${base64Content}`\n },\n include_image_base64: false\n })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`OCR request failed: HTTP ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n if (!result.pages || !Array.isArray(result.pages)) {\n throw new Error('Invalid OCR response format: missing pages array');\n }\n\n const includePageNumbers = options.includePageNumbers !== false;\n const pageSeparator = options.pageSeparator || '\\n\\n';\n \n const textParts = result.pages\n .map((page: any, index: number) => {\n const pageText = page?.markdown || page?.text || '';\n if (!pageText.trim()) {\n return null;\n }\n if (includePageNumbers) {\n return `[Page ${index + 1}]\\n${pageText}`;\n }\n return pageText;\n })\n .filter((text: string | null) => text !== null);\n\n if (textParts.length === 0) {\n throw new Error('No text content found in OCR response');\n }\n\n const extractedText = textParts.join(pageSeparator);\n logger.debug(`Extracted ${result.pages.length} pages from ${fileType} file: ${fileName}`);\n \n return extractedText;\n } catch (error) {\n logger.warn(`Failed to extract text using OCR from ${fileName}: ${error}`);\n throw new Error(`OCR text extraction failed: ${error}`);\n }\n }\n\n private async blobToBase64(blob: Blob): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const result = reader.result as string;\n const base64 = result.split(',')[1];\n resolve(base64);\n };\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n }\n\n private getMimeType(fileType: string): string {\n const mimeTypes: Record<string, string> = {\n 'pdf': 'application/pdf',\n 'png': 'image/png',\n 'jpg': 'image/jpeg',\n 'jpeg': 'image/jpeg',\n 'tiff': 'image/tiff',\n 'tif': 'image/tiff'\n };\n return mimeTypes[fileType.toLowerCase()] || 'application/octet-stream';\n }\n}\n\n","export type { IDocumentExtractor, DocumentExtractionOptions } from './document-extractor-interface';\nexport { PDFJSExtractor } from './pdfjs-extractor';\nexport { LLMOCRExtractor } from './llm-ocr-extractor';\n\nimport { PDFJSExtractor } from './pdfjs-extractor';\nimport { LLMOCRExtractor } from './llm-ocr-extractor';\nimport { createLogger } from '@eclipse-lyra/core';\nimport { toastWarning } from '@eclipse-lyra/core';\nimport type { IDocumentExtractor, DocumentExtractionOptions } from './document-extractor-interface';\nimport type { File } from '@eclipse-lyra/core';\n\nconst logger = createLogger('DocumentExtractor');\n\nexport class DocumentExtractor implements IDocumentExtractor {\n private extractors: IDocumentExtractor[];\n\n constructor() {\n this.extractors = [\n new LLMOCRExtractor(),\n new PDFJSExtractor(),\n ];\n }\n\n canExtract(fileType: string): boolean {\n return this.extractors.some(extractor => extractor.canExtract(fileType));\n }\n\n async extractText(file: File, options?: DocumentExtractionOptions): Promise<string> {\n const fileName = file.getName();\n const fileType = options?.fileType || fileName.split('.').pop()?.toLowerCase() || 'txt';\n\n const availableExtractors = this.extractors.filter(ext => ext.canExtract(fileType));\n \n if (availableExtractors.length === 0) {\n throw new Error(`No extractor available for file type: ${fileType}`);\n }\n\n let lastError: Error | null = null;\n\n for (const extractor of availableExtractors) {\n try {\n logger.debug(`Using ${extractor.constructor.name} for file type: ${fileType}`);\n return await extractor.extractText(file, { ...options, fileType });\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n logger.warn(`${extractor.constructor.name} failed for ${fileName}: ${lastError.message}`);\n \n if (extractor instanceof LLMOCRExtractor && availableExtractors.length > 1) {\n const fallbackExtractor = availableExtractors.find(ext => ext instanceof PDFJSExtractor);\n if (fallbackExtractor) {\n const warningMsg = `Mistral OCR extraction failed, falling back to PDF.js extractor for ${fileName}`;\n logger.warn(warningMsg);\n toastWarning(warningMsg);\n \n try {\n logger.debug(`Using ${fallbackExtractor.constructor.name} as fallback for file type: ${fileType}`);\n return await fallbackExtractor.extractText(file, { ...options, fileType });\n } catch (fallbackError) {\n lastError = fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError));\n logger.warn(`Fallback extraction also failed for ${fileName}: ${lastError.message}`);\n }\n }\n }\n }\n }\n\n throw lastError || new Error(`All extractors failed for file type: ${fileType}`);\n }\n}\n\nexport const defaultDocumentExtractor = new DocumentExtractor();\n\n","type RxdbModule = typeof import('rxdb');\ntype RxdbStorageDexieModule = typeof import('rxdb/plugins/storage-dexie');\ntype RxdbQueryBuilderModule = typeof import('rxdb/plugins/query-builder');\ntype RxdbMigrationSchemaModule = typeof import('rxdb/plugins/migration-schema');\ntype RxdbUpdateModule = typeof import('rxdb/plugins/update');\n\ninterface RxDbModules {\n rxdb: RxdbModule;\n storageDexie: RxdbStorageDexieModule;\n}\n\nlet rxdbModulesPromise: Promise<RxDbModules> | null = null;\nlet pluginsRegistered = false;\n\nasync function importRxdbModules(): Promise<[\n RxdbModule,\n RxdbStorageDexieModule,\n RxdbQueryBuilderModule,\n RxdbMigrationSchemaModule,\n RxdbUpdateModule\n]> {\n return Promise.all([\n import('rxdb'),\n import('rxdb/plugins/storage-dexie'),\n import('rxdb/plugins/query-builder'),\n import('rxdb/plugins/migration-schema'),\n import('rxdb/plugins/update')\n ]);\n}\n\nexport async function getRxDbModules(): Promise<RxDbModules> {\n if (!rxdbModulesPromise) {\n rxdbModulesPromise = importRxdbModules().then(([\n rxdb,\n storageDexie,\n queryBuilder,\n migrationSchema,\n update\n ]) => {\n if (!pluginsRegistered) {\n rxdb.addRxPlugin(queryBuilder.RxDBQueryBuilderPlugin);\n rxdb.addRxPlugin(migrationSchema.RxDBMigrationSchemaPlugin);\n rxdb.addRxPlugin(update.RxDBUpdatePlugin);\n pluginsRegistered = true;\n }\n\n return {\n rxdb,\n storageDexie\n };\n });\n }\n\n return rxdbModulesPromise;\n}\n\n\n","import type { RxDatabase, RxCollection } from 'rxdb';\nimport { rootContext } from '@eclipse-lyra/core';\nimport { workspaceService, File, Directory, FileContentType, TOPIC_WORKSPACE_CONNECTED, TOPIC_WORKSPACE_CHANGED } from '@eclipse-lyra/core';\nimport { subscribe } from '@eclipse-lyra/core';\nimport { createLogger } from '@eclipse-lyra/core';\nimport { embeddingService } from './embedding-service';\nimport { VectorEmbedding, generateSampleVectors, calculateIndexValues, euclideanDistance, cosineSimilarity, SampleVector, IndexValues } from './vector-utils';\nimport { VECTOR_SEARCH_CONFIG, INDEX_FIELD_NAMES } from './utils/constants';\nimport { DocumentChunker, DocumentChunk } from './chunkers/document-chunker';\nimport { DocumentExtractor } from './extractors/document-extractor';\nimport { getRxDbModules } from './rxdb-loader';\n\nconst logger = createLogger('DocumentIndexService');\n\nexport interface DocumentSearchScope {\n includePaths?: string[];\n excludePaths?: string[];\n pathPattern?: string | RegExp;\n tags?: string[];\n metadataFilter?: (doc: IndexedDocument) => boolean;\n}\n\nexport interface IndexedDocument {\n id: string;\n workspacePath: string;\n filePath: string;\n fileName: string;\n fileType: string;\n content: string;\n contentHash: string;\n metadata: {\n size: number;\n lastModified: number;\n language?: string;\n tags?: string[];\n };\n indexedAt: number;\n updatedAt: number;\n}\n\nexport interface DocumentIndexOptions {\n includeContent?: boolean;\n maxFileSize?: number;\n fileTypes?: string[];\n excludePatterns?: string[];\n tags?: string[];\n}\n\ntype DocumentCollection = RxCollection<IndexedDocument>;\ntype VectorCollection = RxCollection<VectorEmbedding>;\n\nclass DocumentIndexService {\n private db?: RxDatabase;\n private documentsCollection?: DocumentCollection;\n private vectorsCollection?: VectorCollection;\n private sampleVectors: SampleVector[] = [];\n private isInitialized = false;\n private readonly DEFAULT_MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB\n private readonly chunker = new DocumentChunker();\n private readonly documentExtractor = new DocumentExtractor();\n private readonly DEFAULT_INDEXABLE_TYPES = [\n 'md', 'txt', 'ts', 'tsx', 'js', 'jsx', 'json', 'geojson',\n 'kml', 'gpx', 'py', 'html', 'css', 'sql', 'xml', 'yaml', 'yml', 'pdf'\n ];\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n logger.info('Initializing document index service with RxDB...');\n\n try {\n const { rxdb, storageDexie } = await getRxDbModules();\n\n this.db = await rxdb.createRxDatabase({\n name: 'document-index-db',\n storage: storageDexie.getRxStorageDexie(),\n ignoreDuplicate: true,\n });\n\n const documentsSchema = {\n version: 0,\n primaryKey: 'id',\n type: 'object',\n properties: {\n id: { type: 'string', maxLength: 500 },\n workspacePath: { type: 'string' },\n filePath: { type: 'string' },\n fileName: { type: 'string' },\n fileType: { type: 'string' },\n content: { type: 'string' },\n contentHash: { type: 'string' },\n metadata: {\n type: 'object',\n properties: {\n size: { type: 'number' },\n lastModified: { type: 'number' },\n language: { type: 'string' },\n tags: {\n type: 'array',\n items: { type: 'string' }\n }\n }\n },\n indexedAt: { type: 'number' },\n updatedAt: { type: 'number' }\n },\n required: ['id', 'workspacePath', 'filePath', 'content', 'contentHash'],\n indexes: ['workspacePath', 'filePath', 'fileType']\n };\n\n const vectorsSchema = {\n version: 1,\n primaryKey: 'id',\n type: 'object',\n properties: {\n id: { type: 'string', maxLength: 500 },\n documentId: { type: 'string', maxLength: 500 },\n embedding: {\n type: 'array',\n items: { type: 'number' }\n },\n idx0: { type: 'number' },\n idx1: { type: 'number' },\n idx2: { type: 'number' },\n idx3: { type: 'number' },\n idx4: { type: 'number' },\n chunkIndex: { type: 'number' },\n chunkStartOffset: { type: 'number' },\n chunkEndOffset: { type: 'number' }\n },\n required: ['id', 'documentId', 'embedding', 'idx0', 'idx1', 'idx2', 'idx3', 'idx4'],\n indexes: ['documentId', 'chunkIndex', 'idx0', 'idx1', 'idx2', 'idx3', 'idx4']\n };\n\n const collectionsToAdd: any = {\n documents: { schema: documentsSchema },\n vectors: { schema: vectorsSchema }\n };\n\n try {\n await this.db.addCollections(collectionsToAdd);\n } catch (error: any) {\n if (error?.code === 'DB8' || error?.message?.includes('already exists')) {\n logger.debug('Collections already exist, using existing collections');\n } else {\n throw error;\n }\n }\n\n this.documentsCollection = this.db.documents as DocumentCollection;\n this.vectorsCollection = this.db.vectors as VectorCollection;\n \n await this.initializeSampleVectors();\n \n await this.handleSchemaMigration();\n \n this.isInitialized = true;\n\n const count = await this.documentsCollection.count().exec();\n const vectorCount = await this.vectorsCollection.count().exec();\n logger.info(`Document index service initialized with ${count} documents and ${vectorCount} embeddings`);\n\n subscribe(TOPIC_WORKSPACE_CONNECTED, (workspace: Directory) => {\n if (workspace) {\n this.handleWorkspaceChange(workspace).catch(err => {\n logger.error(`Failed to handle workspace connection: ${err}`);\n });\n }\n });\n\n subscribe(TOPIC_WORKSPACE_CHANGED, (workspace: Directory) => {\n if (workspace) {\n this.handleWorkspaceChange(workspace).catch(err => {\n logger.error(`Failed to handle workspace change: ${err}`);\n });\n }\n });\n\n logger.info('Document index service initialized');\n } catch (error) {\n logger.error(`Failed to initialize document index service: ${error}`);\n throw error;\n }\n }\n\n private ensureInitialized(): void {\n if (!this.isInitialized || !this.documentsCollection || !this.vectorsCollection) {\n throw new Error('Document index service not initialized. Call initialize() first.');\n }\n }\n\n private async initializeSampleVectors(): Promise<void> {\n if (this.sampleVectors.length > 0) {\n return;\n }\n\n const existingEmbeddings = await this.vectorsCollection!\n .find()\n .limit(1000)\n .exec();\n\n const embeddingArrays = existingEmbeddings.map(v => v.embedding);\n \n this.sampleVectors = generateSampleVectors(\n VECTOR_SEARCH_CONFIG.SAMPLE_VECTOR_COUNT,\n embeddingService.getEmbeddingDimension(),\n embeddingArrays.length > 0 ? embeddingArrays : undefined\n );\n\n logger.info(`Sample vectors initialized for index range method: ${this.sampleVectors.length} vectors, ${existingEmbeddings.length} existing embeddings`);\n }\n\n private generateDocumentId(workspacePath: string, filePath: string): string {\n return `${workspacePath}:${filePath}`;\n }\n\n private async computeContentHash(content: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n private isIndexableFile(file: File, options?: DocumentIndexOptions): boolean {\n const fileName = file.getName().toLowerCase();\n const fileTypes = options?.fileTypes || this.DEFAULT_INDEXABLE_TYPES;\n \n const extension = fileName.split('.').pop();\n if (!extension || !fileTypes.includes(extension)) {\n return false;\n }\n\n if (options?.excludePatterns) {\n for (const pattern of options.excludePatterns) {\n if (fileName.includes(pattern) || file.getWorkspacePath().includes(pattern)) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n private detectLanguage(fileName: string): string {\n const ext = fileName.split('.').pop()?.toLowerCase();\n const langMap: Record<string, string> = {\n 'ts': 'typescript',\n 'tsx': 'typescript',\n 'js': 'javascript',\n 'jsx': 'javascript',\n 'py': 'python',\n 'md': 'markdown',\n 'json': 'json',\n 'geojson': 'geojson',\n 'kml': 'xml',\n 'gpx': 'xml',\n 'html': 'html',\n 'css': 'css',\n 'sql': 'sql',\n 'xml': 'xml',\n 'yaml': 'yaml',\n 'yml': 'yaml',\n 'pdf': 'pdf',\n };\n return langMap[ext || ''] || 'text';\n }\n\n\n async indexDocument(\n file: File,\n options: DocumentIndexOptions = {}\n ): Promise<IndexedDocument> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const workspace = file.getWorkspace();\n const workspacePath = workspace.getName();\n const filePath = file.getWorkspacePath();\n const fileName = file.getName();\n const id = this.generateDocumentId(workspacePath, filePath);\n\n if (!this.isIndexableFile(file, options)) {\n throw new Error(`File type not indexable: ${fileName}`);\n }\n\n try {\n let content: string;\n const fileType = fileName.split('.').pop()?.toLowerCase() || 'txt';\n \n if (this.documentExtractor.canExtract(fileType)) {\n content = await this.documentExtractor.extractText(file, { fileType });\n } else {\n const fileContent = await file.getContents({ contentType: FileContentType.TEXT });\n if (typeof fileContent !== 'string') {\n throw new Error(`File content is not text: ${fileName}`);\n }\n content = fileContent;\n }\n\n if (!content || content.trim().length === 0) {\n throw new Error(`File appears to be empty or text extraction failed: ${fileName}`);\n }\n\n const maxSize = options.maxFileSize || this.DEFAULT_MAX_FILE_SIZE;\n if (content.length > maxSize) {\n throw new Error(`File too large to index: ${fileName} (${content.length} bytes)`);\n }\n\n const contentHash = await this.computeContentHash(content);\n const now = Date.now();\n\n const existing = await this.documentsCollection!.findOne(id).exec();\n const existingDoc = existing ? (existing.toJSON() as IndexedDocument) : null;\n \n const existingTags = existingDoc?.metadata.tags || [];\n const newTags = options.tags || [];\n const mergedTags = [...new Set([...existingTags, ...newTags])];\n const tagsChanged = mergedTags.length !== existingTags.length || \n newTags.some(tag => !existingTags.includes(tag));\n\n if (existingDoc && existingDoc.contentHash === contentHash && !tagsChanged) {\n logger.debug(`Document already indexed and unchanged: ${id}`);\n return existingDoc;\n }\n\n const language = this.detectLanguage(fileName);\n\n let lastModified = now;\n try {\n const fileHandle = (file as any).getHandle?.();\n if (fileHandle) {\n const fileInfo = await fileHandle.getFile();\n lastModified = fileInfo.lastModified;\n }\n } catch (err) {\n logger.debug(`Could not get file modification time: ${err}`);\n }\n\n const contentChanged = !existingDoc || existingDoc.contentHash !== contentHash;\n \n const document: IndexedDocument = {\n id,\n workspacePath,\n filePath,\n fileName,\n fileType,\n content: options.includeContent !== false ? content : '',\n contentHash,\n metadata: {\n size: content.length,\n lastModified,\n language,\n tags: mergedTags,\n },\n indexedAt: existingDoc?.indexedAt || now,\n updatedAt: now,\n };\n\n await this.documentsCollection!.upsert(document);\n\n if (contentChanged) {\n await this.generateAndStoreEmbedding(document);\n } else {\n logger.debug(`Document content unchanged, skipping embedding regeneration: ${id}`);\n }\n\n logger.debug(`Indexed document: ${id}`);\n return document;\n } catch (error) {\n logger.error(`Failed to index document ${id}: ${error}`);\n throw error;\n }\n }\n\n async getDocument(id: string): Promise<IndexedDocument | null> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const doc = await this.documentsCollection!.findOne(id).exec();\n return doc ? (doc.toJSON() as IndexedDocument) : null;\n }\n\n async getDocumentByPath(workspacePath: string, filePath: string): Promise<IndexedDocument | null> {\n const id = this.generateDocumentId(workspacePath, filePath);\n return this.getDocument(id);\n }\n\n async listDocuments(workspacePath?: string): Promise<IndexedDocument[]> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n let query = this.documentsCollection!.find();\n \n if (workspacePath) {\n query = query.where('workspacePath').eq(workspacePath);\n }\n\n const docs = await query.exec();\n return docs.map(doc => doc.toJSON() as IndexedDocument);\n }\n\n async deleteDocument(id: string): Promise<boolean> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const doc = await this.documentsCollection!.findOne(id).exec();\n if (doc) {\n await doc.remove();\n \n const vectors = await this.vectorsCollection!\n .find()\n .where('documentId')\n .eq(id)\n .exec();\n \n for (const vector of vectors) {\n await vector.remove();\n }\n \n logger.debug(`Deleted document ${id} and ${vectors.length} associated embeddings`);\n return true;\n }\n return false;\n }\n\n async deleteDocumentByPath(workspacePath: string, filePath: string): Promise<boolean> {\n const id = this.generateDocumentId(workspacePath, filePath);\n return this.deleteDocument(id);\n }\n\n private async handleSchemaMigration(): Promise<void> {\n if (!this.vectorsCollection || !this.documentsCollection) {\n return;\n }\n\n try {\n const allVectors = await this.vectorsCollection.find().exec();\n const vectorsWithoutChunks = allVectors.filter(v => {\n const data = v.toJSON() as VectorEmbedding;\n return data.chunkIndex === undefined && \n data.chunkStartOffset === undefined && \n data.chunkEndOffset === undefined;\n });\n\n if (vectorsWithoutChunks.length === 0) {\n logger.debug('No vectors need migration - all have chunk information');\n return;\n }\n\n logger.info(`Detected ${vectorsWithoutChunks.length} vectors without chunk information. Invalidating and reindexing...`);\n\n const documentIdsToReindex = new Set<string>();\n \n for (const vector of vectorsWithoutChunks) {\n const data = vector.toJSON() as VectorEmbedding;\n documentIdsToReindex.add(data.documentId);\n await vector.remove();\n }\n\n logger.info(`Removed ${vectorsWithoutChunks.length} old vectors. Reindexing ${documentIdsToReindex.size} documents...`);\n\n for (const documentId of documentIdsToReindex) {\n const doc = await this.documentsCollection.findOne(documentId).exec();\n if (doc) {\n const document = doc.toJSON() as IndexedDocument;\n logger.debug(`Reindexing document: ${document.fileName}`);\n await this.generateAndStoreEmbedding(document);\n }\n }\n\n logger.info(`Schema migration completed. Reindexed ${documentIdsToReindex.size} documents.`);\n } catch (error) {\n logger.error(`Error during schema migration: ${error}`);\n throw error;\n }\n }\n\n async deleteWorkspace(workspacePath: string): Promise<number> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const docs = await this.documentsCollection!\n .find()\n .where('workspacePath')\n .eq(workspacePath)\n .exec();\n\n const count = docs.length;\n for (const doc of docs) {\n await (doc as any).remove();\n }\n\n if (count > 0) {\n logger.info(`Deleted ${count} documents for workspace: ${workspacePath}`);\n }\n\n return count;\n }\n\n async updateDocumentMetadata(\n id: string,\n updates: Partial<Pick<IndexedDocument, 'metadata'>>\n ): Promise<IndexedDocument | null> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const doc = await this.documentsCollection!.findOne(id).exec();\n if (!doc) {\n return null;\n }\n\n const current = doc.toJSON() as IndexedDocument;\n const updated: IndexedDocument = {\n ...current,\n metadata: {\n ...current.metadata,\n ...updates.metadata,\n },\n updatedAt: Date.now(),\n };\n\n await doc.update({ $set: updated });\n\n logger.debug(`Updated document metadata: ${id}`);\n return updated;\n }\n\n async indexWorkspace(\n workspace: Directory,\n options: DocumentIndexOptions = {}\n ): Promise<{ indexed: number; failed: number; errors: string[] }> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n\n const workspacePath = workspace.getName();\n logger.info(`Starting workspace indexing: ${workspacePath}`);\n\n const files = await this.collectFiles(workspace, options);\n logger.info(`Found ${files.length} files to index`);\n\n let indexed = 0;\n let failed = 0;\n const errors: string[] = [];\n\n for (const file of files) {\n try {\n await this.indexDocument(file, options);\n indexed++;\n } catch (error) {\n failed++;\n const errorMsg = `Failed to index ${file.getName()}: ${error}`;\n errors.push(errorMsg);\n logger.warn(errorMsg);\n }\n }\n\n logger.info(`Workspace indexing complete: ${indexed} indexed, ${failed} failed`);\n return { indexed, failed, errors };\n }\n\n private async collectFiles(\n directory: Directory,\n options: DocumentIndexOptions,\n files: File[] = []\n ): Promise<File[]> {\n try {\n const children = await directory.listChildren(false);\n\n for (const child of children) {\n if (child instanceof File) {\n if (this.isIndexableFile(child, options)) {\n files.push(child);\n }\n } else if (child instanceof Directory) {\n await this.collectFiles(child, options, files);\n }\n }\n } catch (error) {\n logger.warn(`Failed to collect files from ${directory.getName()}: ${error}`);\n }\n\n return files;\n }\n\n async reindexDocument(file: File, options: DocumentIndexOptions = {}): Promise<IndexedDocument> {\n const workspace = file.getWorkspace();\n const workspacePath = workspace.getName();\n const filePath = file.getWorkspacePath();\n const id = this.generateDocumentId(workspacePath, filePath);\n\n const existing = await this.getDocument(id);\n const existingTags = existing?.metadata.tags || [];\n const newTags = options.tags || [];\n const mergedTags = [...new Set([...existingTags, ...newTags])];\n\n await this.deleteDocument(id);\n return this.indexDocument(file, {\n ...options,\n tags: mergedTags\n });\n }\n\n async reindexAllDocuments(options: DocumentIndexOptions = {}): Promise<{ total: number; succeeded: number; failed: number }> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const allDocs = await this.listDocuments();\n let succeeded = 0;\n let failed = 0;\n\n for (const doc of allDocs) {\n try {\n const workspace = await workspaceService.getWorkspace();\n if (!workspace || workspace.getName() !== doc.workspacePath) {\n logger.warn(`Workspace not found: ${doc.workspacePath}`);\n failed++;\n continue;\n }\n\n const resource = await workspace.getResource(doc.filePath);\n if (!resource || !(resource instanceof File)) {\n logger.warn(`File not found: ${doc.filePath}`);\n failed++;\n continue;\n }\n\n await this.reindexDocument(resource, options);\n succeeded++;\n } catch (error) {\n logger.error(`Failed to reindex document ${doc.id}: ${error}`);\n failed++;\n }\n }\n\n return {\n total: allDocs.length,\n succeeded,\n failed\n };\n }\n\n async getStats(): Promise<{ totalDocuments: number; byWorkspace: Record<string, number> }> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const totalDocuments = await this.documentsCollection!.count().exec();\n const allDocs = await this.documentsCollection!.find().exec();\n \n const byWorkspace: Record<string, number> = {};\n for (const doc of allDocs) {\n const docData = doc.toJSON() as IndexedDocument;\n const workspacePath = docData.workspacePath;\n byWorkspace[workspacePath] = (byWorkspace[workspacePath] || 0) + 1;\n }\n\n return {\n totalDocuments,\n byWorkspace,\n };\n }\n\n private async handleWorkspaceChange(workspace: Directory): Promise<void> {\n logger.debug('Workspace changed, checking for document updates...');\n // Could implement incremental indexing here\n // For now, just log the change\n }\n\n private async generateAndStoreEmbedding(document: IndexedDocument): Promise<void> {\n try {\n if (!this.vectorsCollection) {\n logger.warn(`Vectors collection not initialized, cannot generate embedding for ${document.id}`);\n return;\n }\n\n await embeddingService.initialize();\n \n if (this.sampleVectors.length === 0) {\n await this.initializeSampleVectors();\n }\n \n if (this.sampleVectors.length === 0) {\n logger.warn(`Sample vectors not initialized, cannot generate embedding for ${document.id}`);\n return;\n }\n\n const chunks = await this.chunker.chunkDocument(document.id, document.content, document.fileName);\n logger.debug(`Document ${document.id} split into ${chunks.length} chunks`);\n\n for (const chunk of chunks) {\n const embedding = await embeddingService.generateEmbedding(chunk.text);\n const indexValues = calculateIndexValues(embedding, this.sampleVectors);\n \n const vectorDoc: VectorEmbedding = {\n id: chunk.id,\n documentId: document.id,\n chunkIndex: chunk.chunkIndex,\n chunkStartOffset: chunk.startOffset,\n chunkEndOffset: chunk.endOffset,\n embedding,\n ...indexValues\n };\n\n await this.vectorsCollection.upsert(vectorDoc);\n }\n\n logger.debug(`Generated and stored ${chunks.length} embeddings for document: ${document.id}`);\n } catch (error) {\n logger.warn(`Failed to generate embedding for document ${document.id}: ${error}`);\n }\n }\n\n async searchSimilar(\n queryText: string,\n options: {\n limit?: number;\n workspacePath?: string;\n fileType?: string;\n indexDistance?: number;\n docsPerIndexSide?: number;\n } = {}\n ): Promise<Array<{ document: IndexedDocument; similarity: number; chunkIndex?: number; chunkStartOffset?: number; chunkEndOffset?: number }>> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const limit = options.limit || 10;\n const indexDistance = options.indexDistance || 2.0;\n const docsPerIndexSide = options.docsPerIndexSide || 100;\n\n if (!this.vectorsCollection || this.sampleVectors.length === 0) {\n logger.warn('Vector search not available: vectors collection or sample vectors not initialized');\n throw new Error('Vector search not available');\n }\n\n const totalVectors = await this.vectorsCollection!.find().exec();\n logger.debug(`Starting vector search with indexDistance=${indexDistance}, limit=${limit}, sampleVectors=${this.sampleVectors.length}, totalIndexedVectors=${totalVectors.length}`);\n\n try {\n await embeddingService.initialize();\n } catch (error) {\n logger.error(`Failed to initialize embedding service for vector search: ${error}`);\n throw new Error(`Embedding service initialization failed: ${error}`);\n }\n\n let queryEmbedding: number[];\n try {\n queryEmbedding = await embeddingService.generateEmbedding(queryText);\n } catch (error) {\n logger.error(`Failed to generate query embedding: ${error}`);\n throw new Error(`Query embedding generation failed: ${error}`);\n }\n \n if (this.sampleVectors.length === 0) {\n logger.warn('Sample vectors not initialized, cannot perform vector search');\n throw new Error('Sample vectors not initialized');\n }\n \n const queryIndexValues = calculateIndexValues(queryEmbedding, this.sampleVectors);\n logger.debug(`Query index values: ${JSON.stringify(queryIndexValues)}`);\n\n const candidateIds = new Set<string>();\n\n try {\n for (const idxKey of INDEX_FIELD_NAMES) {\n const queryValue = queryIndexValues[idxKey];\n const minValue = queryValue - indexDistance;\n const maxValue = queryValue + indexDistance;\n\n logger.debug(`Querying index ${idxKey}: range [${minValue}, ${maxValue}]`);\n\n const candidates = await this.vectorsCollection!\n .find()\n .where(idxKey)\n .gte(minValue)\n .lte(maxValue)\n .limit(docsPerIndexSide)\n .exec();\n\n logger.debug(`Found ${candidates.length} candidates in index ${idxKey}`);\n for (const candidate of candidates) {\n candidateIds.add(candidate.documentId);\n }\n }\n } catch (error) {\n logger.error(`Failed to query vector index: ${error}`);\n throw new Error(`Vector index query failed: ${error}`);\n }\n\n logger.debug(`Total unique candidate IDs: ${candidateIds.size} (out of ${totalVectors.length} indexed vectors)`);\n\n const candidateVectors: VectorEmbedding[] = [];\n try {\n for (const docId of candidateIds) {\n const vectorDocs = await this.vectorsCollection!\n .find()\n .where('documentId')\n .eq(docId)\n .exec();\n \n for (const vectorDoc of vectorDocs) {\n const vectorData = vectorDoc.toJSON() as VectorEmbedding;\n if (vectorData && vectorData.embedding) {\n candidateVectors.push(vectorData);\n } else {\n logger.warn(`Invalid vector data for document ${docId}`);\n }\n }\n }\n } catch (error) {\n logger.error(`Failed to fetch candidate vectors: ${error}`);\n throw new Error(`Failed to fetch candidate vectors: ${error}`);\n }\n\n logger.debug(`Fetched ${candidateVectors.length} candidate vectors`);\n\n const results: Array<{ \n documentId: string; \n similarity: number; \n chunkIndex?: number; \n chunkStartOffset?: number; \n chunkEndOffset?: number;\n }> = [];\n\n for (const vectorDoc of candidateVectors) {\n const cosineSim = cosineSimilarity(queryEmbedding, vectorDoc.embedding);\n const similarity = (cosineSim + 1) / 2;\n results.push({\n documentId: vectorDoc.documentId,\n similarity,\n chunkIndex: vectorDoc.chunkIndex,\n chunkStartOffset: vectorDoc.chunkStartOffset,\n chunkEndOffset: vectorDoc.chunkEndOffset\n });\n }\n\n results.sort((a, b) => b.similarity - a.similarity);\n\n logger.debug(`Computed similarities for ${results.length} candidates, top similarity: ${results[0]?.similarity || 'N/A'}`);\n\n const topResults = results.slice(0, limit);\n const documentResults: Array<{ \n document: IndexedDocument; \n similarity: number; \n chunkIndex?: number; \n chunkStartOffset?: number; \n chunkEndOffset?: number;\n }> = [];\n\n for (const result of topResults) {\n const doc = await this.documentsCollection!.findOne(result.documentId).exec();\n if (doc) {\n const document = doc.toJSON() as IndexedDocument;\n \n if (options.workspacePath && document.workspacePath !== options.workspacePath) {\n continue;\n }\n if (options.fileType && document.fileType !== options.fileType) {\n continue;\n }\n\n documentResults.push({\n document,\n similarity: result.similarity,\n chunkIndex: result.chunkIndex,\n chunkStartOffset: result.chunkStartOffset,\n chunkEndOffset: result.chunkEndOffset\n });\n }\n }\n\n return documentResults;\n }\n\n async indexFileInContext(\n file: File,\n context: DocumentSearchScope,\n options: DocumentIndexOptions = {}\n ): Promise<IndexedDocument> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const workspace = file.getWorkspace();\n const workspacePath = workspace.getName();\n const filePath = file.getWorkspacePath();\n const id = this.generateDocumentId(workspacePath, filePath);\n\n const existing = await this.documentsCollection!.findOne(id).exec();\n const existingDoc = existing ? (existing.toJSON() as IndexedDocument) : null;\n\n const contextTags = context.tags || [];\n const newTags = [...(options.tags || []), ...contextTags];\n\n if (existingDoc) {\n const existingTags = existingDoc.metadata.tags || [];\n const mergedTags = [...new Set([...existingTags, ...newTags])];\n const tagsChanged = mergedTags.length !== existingTags.length || \n newTags.some(tag => !existingTags.includes(tag));\n\n if (tagsChanged) {\n await this.updateDocumentMetadata(existingDoc.id, {\n metadata: {\n ...existingDoc.metadata,\n tags: mergedTags\n }\n });\n logger.debug(`Added tags to existing document: ${id}`);\n return {\n ...existingDoc,\n metadata: {\n ...existingDoc.metadata,\n tags: mergedTags\n }\n };\n } else {\n logger.debug(`Document already has all tags: ${id}`);\n return existingDoc;\n }\n }\n\n return this.indexDocument(file, {\n ...options,\n tags: newTags\n });\n }\n\n async indexFilesInContext(\n files: File[],\n context: DocumentSearchScope,\n options: DocumentIndexOptions = {}\n ): Promise<{ succeeded: number; failed: number }> {\n let succeeded = 0;\n let failed = 0;\n const contextTags = context.tags || [];\n\n for (const file of files) {\n try {\n await this.indexDocument(file, {\n ...options,\n tags: [...(options.tags || []), ...contextTags]\n });\n succeeded++;\n logger.debug(`Indexed file with context tags: ${file.getWorkspacePath()}`);\n } catch (error) {\n logger.error(`Failed to index file ${file.getWorkspacePath()}: ${error}`);\n failed++;\n }\n }\n\n return { succeeded, failed };\n }\n\n async reindexFileInContext(\n file: File,\n context: DocumentSearchScope,\n options: DocumentIndexOptions = {}\n ): Promise<IndexedDocument> {\n const contextTags = context.tags || [];\n return this.reindexDocument(file, {\n ...options,\n tags: [...(options.tags || []), ...contextTags]\n });\n }\n\n async removeFileFromContext(file: File, context: DocumentSearchScope): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n this.ensureInitialized();\n\n const document = await this.getDocumentByPath(\n file.getWorkspace().getName(),\n file.getWorkspacePath()\n );\n\n if (document && context.tags && context.tags.length > 0) {\n const contextTags = new Set(context.tags);\n const updatedTags = (document.metadata.tags || []).filter(tag => !contextTags.has(tag));\n \n if (updatedTags.length !== document.metadata.tags?.length) {\n await this.updateDocumentMetadata(document.id, {\n metadata: {\n ...document.metadata,\n tags: updatedTags\n }\n });\n }\n }\n }\n\n async clearContext(context: DocumentSearchScope): Promise<void> {\n if (!context.tags || context.tags.length === 0) {\n return;\n }\n\n const contextTags = new Set(context.tags);\n const allDocs = await this.listDocuments();\n\n for (const doc of allDocs) {\n const hasContextTag = doc.metadata.tags?.some(tag => contextTags.has(tag));\n if (hasContextTag) {\n const updatedTags = doc.metadata.tags!.filter(tag => !contextTags.has(tag));\n try {\n const workspace = await workspaceService.getWorkspace();\n if (workspace && workspace.getName() === doc.workspacePath) {\n const resource = await workspace.getResource(doc.filePath);\n if (resource instanceof File) {\n await this.indexDocument(resource, {\n tags: updatedTags\n });\n }\n }\n } catch (error) {\n logger.warn(`Failed to clear context tags from ${doc.filePath}: ${error}`);\n }\n }\n }\n }\n\n async getFilePathsInContext(context: DocumentSearchScope): Promise<string[]> {\n if (!context.tags || context.tags.length === 0) {\n return [];\n }\n\n const contextTags = new Set(context.tags);\n const allDocs = await this.listDocuments();\n \n return allDocs\n .filter(doc => doc.metadata.tags?.some(tag => contextTags.has(tag)))\n .map(doc => doc.filePath);\n }\n}\n\nexport const documentIndexService = new DocumentIndexService();\nrootContext.put('documentIndexService', documentIndexService);\n","import { workspaceService, Directory } from '@eclipse-lyra/core';\nimport { createLogger } from '@eclipse-lyra/core';\n\nconst logger = createLogger('WorkspaceUtils');\n\nexport interface WorkspacePathResult {\n workspace: Directory;\n workspacePath: string;\n}\n\nexport async function getWorkspacePath(\n providedPath?: string\n): Promise<WorkspacePathResult | null> {\n const workspace = await workspaceService.getWorkspace();\n \n if (!workspace) {\n logger.warn('No workspace connected');\n return null;\n }\n\n const workspacePath = providedPath || workspace.getName();\n \n if (!workspacePath) {\n logger.warn('No workspace path available');\n return null;\n }\n\n return { workspace, workspacePath };\n}\n\nexport async function requireWorkspacePath(\n providedPath?: string\n): Promise<WorkspacePathResult> {\n const result = await getWorkspacePath(providedPath);\n if (!result) {\n throw new Error('Workspace not available');\n }\n return result;\n}\n\n","export interface QueryTermsOptions {\n minTermLength?: number;\n caseSensitive?: boolean;\n}\n\nconst DEFAULT_MIN_TERM_LENGTH = 2;\n\nexport function extractQueryTerms(\n query: string,\n options: QueryTermsOptions = {}\n): string[] {\n if (!query || !query.trim()) {\n return [];\n }\n\n const minLength = options.minTermLength ?? DEFAULT_MIN_TERM_LENGTH;\n const text = options.caseSensitive ? query : query.toLowerCase();\n \n return text\n .split(/\\s+/)\n .filter(term => term.length >= minLength);\n}\n\nexport function normalizeQuery(query: string): string {\n return query.toLowerCase().trim();\n}\n\n","import { extractQueryTerms } from './query-utils';\n\nexport interface SnippetExtractionOptions {\n maxSnippets?: number;\n snippetLength?: number;\n minGap?: number;\n}\n\nconst DEFAULT_MAX_SNIPPETS = 10;\nconst DEFAULT_SNIPPET_LENGTH = 400;\nconst DEFAULT_MIN_GAP = 400;\n\ninterface SnippetCandidate {\n snippet: string;\n score: number;\n start: number;\n}\n\nexport class SnippetExtractor {\n private readonly maxSnippets: number;\n private readonly snippetLength: number;\n private readonly minGap: number;\n\n constructor(options: SnippetExtractionOptions = {}) {\n this.maxSnippets = options.maxSnippets ?? DEFAULT_MAX_SNIPPETS;\n this.snippetLength = options.snippetLength ?? DEFAULT_SNIPPET_LENGTH;\n this.minGap = options.minGap ?? DEFAULT_MIN_GAP;\n }\n\n extractSnippets(\n content: string,\n queryTerms: string[],\n maxSnippets?: number\n ): string[] {\n const effectiveMaxSnippets = maxSnippets ?? this.maxSnippets;\n \n if (queryTerms.length === 0) {\n return [];\n }\n\n const contentLower = content.toLowerCase();\n const snippetCandidates: SnippetCandidate[] = [];\n const seenSnippets = new Set<string>();\n\n for (const term of queryTerms) {\n let index = contentLower.indexOf(term);\n \n while (index !== -1) {\n const start = Math.max(0, index - this.snippetLength / 2);\n const end = Math.min(content.length, index + term.length + this.snippetLength / 2);\n const snippet = content.substring(start, end).trim();\n const snippetKey = `${start}-${end}`;\n \n if (snippet && !seenSnippets.has(snippetKey)) {\n seenSnippets.add(snippetKey);\n \n const score = this.calculateSnippetScore(snippet, queryTerms);\n snippetCandidates.push({ snippet, score, start });\n }\n\n index = contentLower.indexOf(term, index + 1);\n }\n }\n\n if (snippetCandidates.length === 0 && queryTerms.length > 0) {\n const firstTerm = queryTerms[0];\n const index = contentLower.indexOf(firstTerm);\n if (index !== -1) {\n const start = Math.max(0, index - this.snippetLength);\n const end = Math.min(content.length, index + firstTerm.length + this.snippetLength);\n const snippet = content.substring(start, end).trim();\n if (snippet) {\n snippetCandidates.push({ snippet, score: 10, start });\n }\n }\n }\n\n snippetCandidates.sort((a, b) => {\n if (b.score !== a.score) {\n return b.score - a.score;\n }\n return a.start - b.start;\n });\n\n return this.selectNonOverlappingSnippets(snippetCandidates, effectiveMaxSnippets);\n }\n\n private calculateSnippetScore(snippet: string, queryTerms: string[]): number {\n const snippetLower = snippet.toLowerCase();\n let score = 0;\n \n for (const qTerm of queryTerms) {\n const termMatches = (snippetLower.match(\n new RegExp(qTerm.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi')\n ) || []).length;\n score += termMatches * 10;\n }\n \n const fullQuery = queryTerms.join(' ');\n if (snippetLower.includes(fullQuery)) {\n score += 50;\n }\n \n const uniqueTermsFound = queryTerms.filter(t => snippetLower.includes(t)).length;\n score += uniqueTermsFound * 20;\n \n const termDensity = uniqueTermsFound / queryTerms.length;\n score += termDensity * 30;\n \n return score;\n }\n\n private selectNonOverlappingSnippets(\n candidates: SnippetCandidate[],\n maxSnippets: number\n ): string[] {\n const selectedSnippets: string[] = [];\n const usedRanges: Array<{ start: number; end: number }> = [];\n\n for (const candidate of candidates) {\n if (selectedSnippets.length >= maxSnippets) break;\n\n const candidateStart = candidate.start;\n const candidateEnd = candidate.start + candidate.snippet.length;\n\n const overlaps = usedRanges.some(range => {\n return !(candidateEnd < range.start - this.minGap || candidateStart > range.end + this.minGap);\n });\n\n if (!overlaps) {\n selectedSnippets.push(candidate.snippet);\n usedRanges.push({ start: candidateStart, end: candidateEnd });\n }\n }\n\n return selectedSnippets;\n }\n\n extractSimpleSnippet(content: string, maxLength: number = 500): string {\n const preview = content.substring(0, maxLength);\n return preview + (content.length > maxLength ? '...' : '');\n }\n\n extractContextSnippets(\n content: string,\n query: string,\n contextLength: number = 150\n ): Array<{ start: number; end: number; matchIndex: number }> {\n const queryLower = query.toLowerCase();\n const contentLower = content.toLowerCase();\n const matches: number[] = [];\n let index = contentLower.indexOf(queryLower);\n\n while (index !== -1) {\n matches.push(index);\n index = contentLower.indexOf(queryLower, index + 1);\n }\n\n if (matches.length === 0) {\n return [];\n }\n\n const snippets: Array<{ start: number; end: number; matchIndex: number }> = [];\n for (const matchIndex of matches) {\n const start = Math.max(0, matchIndex - contextLength);\n const end = Math.min(content.length, matchIndex + query.length + contextLength);\n snippets.push({ start, end, matchIndex });\n }\n\n return snippets;\n }\n}\n\nexport const defaultSnippetExtractor = new SnippetExtractor();\n\n","import { IndexedDocument } from '../document-index-service';\nimport { normalizeQuery, extractQueryTerms } from '../utils/query-utils';\nimport { RELEVANCE_WEIGHTS } from '../utils/constants';\n\nexport class RelevanceCalculator {\n calculateRelevance(\n doc: IndexedDocument,\n query: string\n ): number {\n const queryLower = normalizeQuery(query);\n const queryTerms = extractQueryTerms(query);\n\n let score = 0;\n\n const fileNameLower = doc.fileName.toLowerCase();\n const filePathLower = doc.filePath.toLowerCase();\n const contentLower = doc.content.toLowerCase();\n\n const fileNameMatches = queryTerms.filter(term => fileNameLower.includes(term)).length;\n const filePathMatches = queryTerms.filter(term => filePathLower.includes(term)).length;\n const contentMatches = queryTerms.filter(term => contentLower.includes(term)).length;\n\n score += fileNameMatches * RELEVANCE_WEIGHTS.FILE_NAME_MATCH;\n score += filePathMatches * RELEVANCE_WEIGHTS.FILE_PATH_MATCH;\n score += contentMatches * RELEVANCE_WEIGHTS.CONTENT_MATCH;\n\n if (fileNameLower.includes(queryLower)) {\n score += RELEVANCE_WEIGHTS.FILE_NAME_EXACT;\n }\n\n if (filePathLower.includes(queryLower)) {\n score += RELEVANCE_WEIGHTS.FILE_PATH_EXACT;\n }\n\n const exactPhraseMatches = (contentLower.match(\n new RegExp(queryLower.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g')\n ) || []).length;\n score += exactPhraseMatches * RELEVANCE_WEIGHTS.EXACT_PHRASE;\n\n const totalTerms = queryTerms.length;\n const matchedTerms = queryTerms.filter(term => contentLower.includes(term)).length;\n const termCoverage = totalTerms > 0 ? matchedTerms / totalTerms : 0;\n score += termCoverage * RELEVANCE_WEIGHTS.TERM_COVERAGE;\n\n return score;\n }\n\n calculateFileNameRelevance(\n doc: IndexedDocument,\n fileName: string\n ): number {\n const docNameLower = doc.fileName.toLowerCase();\n const fileNameLower = fileName.toLowerCase();\n \n if (docNameLower === fileNameLower) {\n return 100;\n }\n if (docNameLower.includes(fileNameLower)) {\n return 80;\n }\n return 0;\n }\n}\n\nexport const relevanceCalculator = new RelevanceCalculator();\n\n","import { RAGSearchResult } from '../rag-service';\nimport { SnippetExtractor } from '../utils/snippet-extractor';\nimport { SNIPPET_LENGTHS } from '../utils/constants';\n\nexport class RAGResultFormatter {\n constructor(private snippetExtractor: SnippetExtractor) {}\n\n formatRAGContext(results: RAGSearchResult[]): string {\n if (results.length === 0) {\n return '';\n }\n\n const sections = results.map((result, idx) => {\n const doc = result.document;\n const snippets = result.matchedSnippets\n .map((s, i) => ` [Snippet ${i + 1}]\\n ${s}`)\n .join('\\n\\n');\n\n return `[Document ${idx + 1}: ${doc.fileName} (${doc.filePath})]\nRelevance: ${result.relevance.toFixed(2)}\n${snippets.length > 0 ? `Relevant snippets:\\n${snippets}` : `Content preview: ${this.snippetExtractor.extractSimpleSnippet(doc.content, SNIPPET_LENGTHS.PREVIEW)}`}\n---`;\n }).join('\\n\\n');\n\n return `Here are relevant documents from the workspace that might help answer the question:\n\n${sections}\n\nUse the information from these documents to provide a helpful answer. Pay special attention to numbers, percentages, dates, and specific values mentioned in the snippets. If the documents don't contain relevant information, you can still answer based on your general knowledge.`;\n }\n\n formatSearchResults(results: RAGSearchResult[]): Array<{\n file: string;\n path: string;\n relevance: string;\n language?: string;\n size: number;\n snippets: string[];\n preview: string;\n }> {\n return results.map(r => ({\n file: r.document.fileName,\n path: r.document.filePath,\n relevance: r.relevance.toFixed(2),\n language: r.document.metadata.language,\n size: r.document.metadata.size,\n snippets: r.matchedSnippets,\n preview: this.snippetExtractor.extractSimpleSnippet(r.document.content, 200) + '...'\n }));\n }\n\n formatCommandResults(results: RAGSearchResult[]): Array<{\n file: string;\n path: string;\n relevance: number;\n snippets: string[];\n }> {\n return results.map(r => ({\n file: r.document.fileName,\n path: r.document.filePath,\n relevance: r.relevance,\n snippets: r.matchedSnippets\n }));\n }\n}\n\n","import { documentIndexService, IndexedDocument, DocumentSearchScope } from './document-index-service';\nimport { createLogger } from '@eclipse-lyra/core';\nimport { getWorkspacePath } from './utils/workspace-utils';\nimport { extractQueryTerms, normalizeQuery } from './utils/query-utils';\nimport { SnippetExtractor } from './utils/snippet-extractor';\nimport { SEARCH_CONFIG, SNIPPET_LENGTHS } from './utils/constants';\nimport { relevanceCalculator } from './services/relevance-calculator';\nimport { RAGResultFormatter } from './services/rag-result-formatter';\n\nconst logger = createLogger('RAGService');\nconst snippetExtractor = new SnippetExtractor();\nconst resultFormatter = new RAGResultFormatter(snippetExtractor);\n\nexport interface RAGSearchOptions {\n limit?: number;\n fileType?: string;\n workspacePath?: string;\n minRelevance?: number;\n filePath?: string;\n fileName?: string;\n documentSearchScope?: DocumentSearchScope;\n}\n\nexport interface RAGSearchResult {\n document: IndexedDocument;\n relevance: number;\n matchedSnippets: string[];\n}\n\nclass RAGService {\n async searchDocuments(\n query: string,\n options: RAGSearchOptions = {}\n ): Promise<RAGSearchResult[]> {\n const limit = Math.min(options.limit || SEARCH_CONFIG.DEFAULT_LIMIT, SEARCH_CONFIG.MAX_LIMIT);\n const workspaceResult = await getWorkspacePath(options.workspacePath);\n \n if (!workspaceResult) {\n logger.warn('No workspace connected, cannot search documents');\n return [];\n }\n\n const { workspacePath } = workspaceResult;\n\n if (options.filePath) {\n const specificDoc = await documentIndexService.getDocumentByPath(workspacePath, options.filePath);\n if (specificDoc) {\n const queryTerms = extractQueryTerms(query);\n const matchedSnippets = queryTerms.length > 0 \n ? snippetExtractor.extractSnippets(specificDoc.content, queryTerms, 3)\n : [snippetExtractor.extractSimpleSnippet(specificDoc.content, SNIPPET_LENGTHS.PREVIEW)];\n return [{\n document: specificDoc,\n relevance: 100,\n matchedSnippets\n }];\n }\n logger.warn(`Document not found: ${options.filePath}`);\n return [];\n }\n\n if (options.fileName) {\n const allDocs = await documentIndexService.listDocuments(workspacePath);\n const fileNameLower = options.fileName.toLowerCase();\n const matchingDocs = allDocs.filter(doc => {\n const docNameLower = doc.fileName.toLowerCase();\n return docNameLower === fileNameLower || docNameLower.includes(fileNameLower);\n });\n \n if (matchingDocs.length > 0) {\n const results: RAGSearchResult[] = [];\n const queryTerms = extractQueryTerms(query);\n for (const doc of matchingDocs.slice(0, limit)) {\n const matchedSnippets = queryTerms.length > 0\n ? snippetExtractor.extractSnippets(doc.content, queryTerms, 3)\n : [snippetExtractor.extractSimpleSnippet(doc.content, SNIPPET_LENGTHS.PREVIEW)];\n results.push({\n document: doc,\n relevance: relevanceCalculator.calculateFileNameRelevance(doc, options.fileName),\n matchedSnippets\n });\n }\n return results;\n }\n logger.warn(`No documents found with name: ${options.fileName}`);\n return [];\n }\n\n if (!query || !query.trim()) {\n logger.warn('No query provided and no filePath/fileName specified');\n return [];\n }\n\n try {\n const vectorResults = await documentIndexService.searchSimilar(query, {\n limit: limit * 2,\n workspacePath,\n fileType: options.fileType\n });\n\n const results: RAGSearchResult[] = [];\n\n for (const { document, similarity, chunkStartOffset, chunkEndOffset } of vectorResults) {\n if (!this.matchesContextScope(document, options.documentSearchScope)) {\n continue;\n }\n\n const relevance = similarity * 100;\n \n if (options.minRelevance && relevance < options.minRelevance) {\n continue;\n }\n\n const queryLower = normalizeQuery(query);\n const queryTerms = extractQueryTerms(query);\n \n let matchedSnippets: string[];\n \n if (chunkStartOffset !== undefined && chunkEndOffset !== undefined) {\n const chunkText = document.content.substring(\n Math.max(0, chunkStartOffset),\n Math.min(document.content.length, chunkEndOffset)\n );\n \n if (chunkText.trim().length > 0) {\n matchedSnippets = [chunkText.trim()];\n } else {\n matchedSnippets = snippetExtractor.extractSnippets(document.content, queryTerms, 15);\n }\n } else {\n matchedSnippets = snippetExtractor.extractSnippets(document.content, queryTerms, 15);\n }\n \n if (matchedSnippets.length === 0 && queryLower.length > 0) {\n if (chunkStartOffset !== undefined && chunkEndOffset !== undefined) {\n const chunkText = document.content.substring(\n Math.max(0, chunkStartOffset),\n Math.min(document.content.length, chunkEndOffset)\n );\n if (chunkText.trim().length > 0) {\n matchedSnippets = [chunkText.trim()];\n } else {\n matchedSnippets = snippetExtractor.extractSnippets(document.content, [queryLower], 10);\n }\n } else {\n matchedSnippets = snippetExtractor.extractSnippets(document.content, [queryLower], 10);\n }\n }\n\n results.push({\n document,\n relevance,\n matchedSnippets\n });\n\n if (results.length >= limit) {\n break;\n }\n }\n\n if (results.length === 0) {\n logger.debug('Vector search returned no results, falling back to text search');\n return this.fallbackTextSearch(query, options);\n }\n\n return results;\n } catch (error) {\n logger.warn(`Vector search failed, falling back to text search: ${error}`);\n logger.debug(`Vector search error details: ${error}`);\n return this.fallbackTextSearch(query, options);\n }\n }\n\n private async fallbackTextSearch(\n query: string,\n options: RAGSearchOptions = {}\n ): Promise<RAGSearchResult[]> {\n const limit = Math.min(options.limit || SEARCH_CONFIG.DEFAULT_LIMIT, SEARCH_CONFIG.MAX_LIMIT);\n const workspaceResult = await getWorkspacePath(options.workspacePath);\n \n if (!workspaceResult) {\n logger.warn('No workspace connected, cannot perform text search');\n return [];\n }\n\n const { workspacePath } = workspaceResult;\n const allDocuments = await documentIndexService.listDocuments(workspacePath);\n const queryTerms = extractQueryTerms(query);\n\n const results: RAGSearchResult[] = [];\n\n for (const doc of allDocuments) {\n if (options.fileType && doc.fileType !== options.fileType) {\n continue;\n }\n\n if (!this.matchesContextScope(doc, options.documentSearchScope)) {\n continue;\n }\n\n const relevance = relevanceCalculator.calculateRelevance(doc, query);\n \n if (options.minRelevance && relevance < options.minRelevance) {\n continue;\n }\n\n const matchedSnippets = snippetExtractor.extractSnippets(doc.content, queryTerms, 3);\n\n results.push({\n document: doc,\n relevance,\n matchedSnippets\n });\n }\n\n results.sort((a, b) => b.relevance - a.relevance);\n return results.slice(0, limit);\n }\n\n formatRAGContext(results: RAGSearchResult[]): string {\n return resultFormatter.formatRAGContext(results);\n }\n\n private matchesContextScope(doc: IndexedDocument, scope?: DocumentSearchScope): boolean {\n if (!scope) {\n return true;\n }\n\n if (scope.includePaths && scope.includePaths.length > 0) {\n const matches = scope.includePaths.some(pattern => {\n if (pattern.includes('*') || pattern.includes('?')) {\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$');\n return regex.test(doc.filePath);\n }\n return doc.filePath.startsWith(pattern) || doc.filePath === pattern;\n });\n if (!matches) {\n return false;\n }\n }\n\n if (scope.excludePaths && scope.excludePaths.length > 0) {\n const matches = scope.excludePaths.some(pattern => {\n if (pattern.includes('*') || pattern.includes('?')) {\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$');\n return regex.test(doc.filePath);\n }\n return doc.filePath.startsWith(pattern) || doc.filePath === pattern;\n });\n if (matches) {\n return false;\n }\n }\n\n if (scope.pathPattern) {\n const regex = scope.pathPattern instanceof RegExp \n ? scope.pathPattern \n : new RegExp(scope.pathPattern);\n if (!regex.test(doc.filePath)) {\n return false;\n }\n }\n\n if (scope.tags && scope.tags.length > 0) {\n const docTags = doc.metadata.tags || [];\n const hasAllTags = scope.tags.every(tag => docTags.includes(tag));\n if (!hasAllTags) {\n return false;\n }\n }\n\n if (scope.metadataFilter) {\n if (!scope.metadataFilter(doc)) {\n return false;\n }\n }\n\n return true;\n }\n\n}\n\nexport const ragService = new RAGService();\n\nexport async function searchWorkspaceDocuments(\n query: string,\n options: RAGSearchOptions = {}\n): Promise<RAGSearchResult[]> {\n const workspaceResult = await getWorkspacePath(options.workspacePath);\n \n if (!workspaceResult) {\n logger.warn('No workspace connected, cannot search documents');\n return [];\n }\n\n return ragService.searchDocuments(query, {\n ...options,\n workspacePath: workspaceResult.workspacePath\n });\n}\n\n"],"names":["logger","DEFAULT_CHUNK_SIZE","DEFAULT_CHUNK_OVERLAP","LangChainChunker","FallbackChunker","LLMOCRExtractor","PDFJSExtractor","snippetExtractor"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { IndexedDocument, DocumentSearchScope } from './document-index-service';
2
+ export interface RAGSearchOptions {
3
+ limit?: number;
4
+ fileType?: string;
5
+ workspacePath?: string;
6
+ minRelevance?: number;
7
+ filePath?: string;
8
+ fileName?: string;
9
+ documentSearchScope?: DocumentSearchScope;
10
+ }
11
+ export interface RAGSearchResult {
12
+ document: IndexedDocument;
13
+ relevance: number;
14
+ matchedSnippets: string[];
15
+ }
16
+ declare class RAGService {
17
+ searchDocuments(query: string, options?: RAGSearchOptions): Promise<RAGSearchResult[]>;
18
+ private fallbackTextSearch;
19
+ formatRAGContext(results: RAGSearchResult[]): string;
20
+ private matchesContextScope;
21
+ }
22
+ export declare const ragService: RAGService;
23
+ export declare function searchWorkspaceDocuments(query: string, options?: RAGSearchOptions): Promise<RAGSearchResult[]>;
24
+ export {};
25
+ //# sourceMappingURL=rag-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-service.d.ts","sourceRoot":"","sources":["../src/rag-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,eAAe,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAatG,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,cAAM,UAAU;IACN,eAAe,CACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC;YA4If,kBAAkB;IA8ChC,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM;IAIpD,OAAO,CAAC,mBAAmB;CAyD9B;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC;AAE3C,wBAAsB,wBAAwB,CAC1C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B"}