uilint-duplicates 0.2.27
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/dist/chunk-DURWZZLU.js +1941 -0
- package/dist/chunk-DURWZZLU.js.map +1 -0
- package/dist/index.d.ts +783 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +1 -0
- package/dist/node.js +55 -0
- package/dist/node.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/embeddings/chunker.ts","../src/embeddings/ollama-embeddings.ts","../src/query/api.ts","../src/cache/incremental-indexer.ts","../src/index/vector-store.ts","../src/index/metadata-store.ts","../src/cache/file-tracker.ts","../src/detection/scorer.ts","../src/detection/duplicate-finder.ts"],"sourcesContent":["/**\n * Code chunker - extracts meaningful code units from TypeScript/TSX files\n *\n * Uses @typescript-eslint/typescript-estree for parsing.\n * Supports splitting large components into smaller, embeddable chunks.\n */\n\nimport { parse, TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/typescript-estree\";\nimport type { CodeChunk, ChunkKind, ChunkMetadata, ChunkingOptions } from \"./types.js\";\n\nconst DEFAULT_MAX_LINES = 100;\nconst MIN_SECTION_LINES = 3;\n\n/**\n * Hash function for generating chunk IDs\n * Simple djb2 hash - consistent with existing codebase pattern\n */\nfunction hashChunk(content: string, filePath: string, startLine: number): string {\n let hash = 5381;\n const input = `${filePath}:${startLine}:${content}`;\n for (let i = 0; i < input.length; i++) {\n hash = (hash * 33) ^ input.charCodeAt(i);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Parse a file and extract code chunks\n */\nexport function chunkFile(\n filePath: string,\n content: string,\n options: ChunkingOptions = {}\n): CodeChunk[] {\n const {\n minLines = 3,\n maxLines = DEFAULT_MAX_LINES,\n includeAnonymous = false,\n kinds,\n splitStrategy = \"jsx-children\",\n } = options;\n\n // Parse the file\n let ast: TSESTree.Program;\n try {\n ast = parse(content, {\n jsx: true,\n loc: true,\n range: true,\n tokens: false,\n comment: false,\n });\n } catch (error) {\n // Return empty array if parsing fails\n console.warn(`Failed to parse ${filePath}:`, error);\n return [];\n }\n\n const chunks: CodeChunk[] = [];\n const lines = content.split(\"\\n\");\n\n // Track exports for metadata\n const exportedNames = new Set<string>();\n let defaultExportName: string | null = null;\n\n // First pass: collect exports\n for (const node of ast.body) {\n if (node.type === AST_NODE_TYPES.ExportNamedDeclaration) {\n if (node.declaration) {\n const names = getDeclarationNames(node.declaration);\n names.forEach((name) => exportedNames.add(name));\n }\n if (node.specifiers) {\n node.specifiers.forEach((spec) => {\n if (spec.type === AST_NODE_TYPES.ExportSpecifier) {\n exportedNames.add(\n spec.exported.type === AST_NODE_TYPES.Identifier\n ? spec.exported.name\n : spec.exported.value\n );\n }\n });\n }\n } else if (node.type === AST_NODE_TYPES.ExportDefaultDeclaration) {\n if (node.declaration.type === AST_NODE_TYPES.Identifier) {\n defaultExportName = node.declaration.name;\n } else if (\n node.declaration.type === AST_NODE_TYPES.FunctionDeclaration &&\n node.declaration.id\n ) {\n defaultExportName = node.declaration.id.name;\n }\n }\n }\n\n // Second pass: extract chunks\n function visit(node: TSESTree.Node) {\n // Check function declarations\n if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) {\n const chunk = processFunction(\n node,\n node.id.name,\n filePath,\n content,\n lines,\n exportedNames,\n defaultExportName\n );\n if (chunk && shouldIncludeChunk(chunk, minLines, includeAnonymous, kinds)) {\n // Check if chunk needs splitting\n const lineCount = chunk.endLine - chunk.startLine + 1;\n if (lineCount > maxLines && splitStrategy !== \"none\") {\n const splitChunks = splitLargeChunk(node, chunk, content, lines, maxLines, splitStrategy);\n chunks.push(...splitChunks.filter(c => shouldIncludeChunk(c, minLines, includeAnonymous, kinds)));\n } else {\n chunks.push(chunk);\n }\n }\n }\n\n // Check variable declarations with arrow functions\n if (node.type === AST_NODE_TYPES.VariableDeclaration) {\n for (const decl of node.declarations) {\n if (\n decl.id.type === AST_NODE_TYPES.Identifier &&\n decl.init &&\n (decl.init.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n decl.init.type === AST_NODE_TYPES.FunctionExpression)\n ) {\n const chunk = processFunction(\n decl.init,\n decl.id.name,\n filePath,\n content,\n lines,\n exportedNames,\n defaultExportName,\n node // Use the variable declaration for location\n );\n if (chunk && shouldIncludeChunk(chunk, minLines, includeAnonymous, kinds)) {\n // Check if chunk needs splitting\n const lineCount = chunk.endLine - chunk.startLine + 1;\n if (lineCount > maxLines && splitStrategy !== \"none\") {\n const splitChunks = splitLargeChunk(decl.init, chunk, content, lines, maxLines, splitStrategy);\n chunks.push(...splitChunks.filter(c => shouldIncludeChunk(c, minLines, includeAnonymous, kinds)));\n } else {\n chunks.push(chunk);\n }\n }\n }\n }\n }\n\n // Recursively visit children\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (node as unknown as Record<string, unknown>)[key];\n if (child && typeof child === \"object\") {\n if (Array.isArray(child)) {\n child.forEach((c) => {\n if (c && typeof c === \"object\" && \"type\" in c) {\n visit(c as TSESTree.Node);\n }\n });\n } else if (\"type\" in child) {\n visit(child as TSESTree.Node);\n }\n }\n }\n }\n\n visit(ast);\n return chunks;\n}\n\nfunction processFunction(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression,\n name: string,\n filePath: string,\n content: string,\n lines: string[],\n exportedNames: Set<string>,\n defaultExportName: string | null,\n locationNode?: TSESTree.Node\n): CodeChunk | null {\n const loc = (locationNode || node).loc;\n if (!loc) return null;\n\n const startLine = loc.start.line;\n const endLine = loc.end.line;\n const startColumn = loc.start.column;\n const endColumn = loc.end.column;\n\n // Extract the chunk content\n const chunkContent = lines.slice(startLine - 1, endLine).join(\"\\n\");\n\n // Determine the kind\n const kind = classifyFunction(name, node);\n\n // Extract metadata\n const metadata = extractMetadata(node, name, exportedNames, defaultExportName);\n\n return {\n id: hashChunk(chunkContent, filePath, startLine),\n filePath,\n startLine,\n endLine,\n startColumn,\n endColumn,\n kind,\n name,\n content: chunkContent,\n metadata,\n };\n}\n\nfunction classifyFunction(\n name: string,\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n): ChunkKind {\n // Check for hook (useXxx pattern)\n if (/^use[A-Z]/.test(name)) {\n return \"hook\";\n }\n\n // Check for component (PascalCase + returns JSX)\n if (/^[A-Z]/.test(name) && containsJSX(node)) {\n return \"component\";\n }\n\n // Check for JSX fragment (returns JSX but not PascalCase)\n if (containsJSX(node)) {\n return \"jsx-fragment\";\n }\n\n return \"function\";\n}\n\nfunction containsJSX(node: TSESTree.Node): boolean {\n let found = false;\n\n function search(n: TSESTree.Node) {\n if (found) return;\n if (n.type === AST_NODE_TYPES.JSXElement || n.type === AST_NODE_TYPES.JSXFragment) {\n found = true;\n return;\n }\n for (const key of Object.keys(n)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (n as unknown as Record<string, unknown>)[key];\n if (child && typeof child === \"object\") {\n if (Array.isArray(child)) {\n child.forEach((c) => {\n if (c && typeof c === \"object\" && \"type\" in c) {\n search(c as TSESTree.Node);\n }\n });\n } else if (\"type\" in child) {\n search(child as TSESTree.Node);\n }\n }\n }\n }\n\n search(node);\n return found;\n}\n\nfunction extractMetadata(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression,\n name: string,\n exportedNames: Set<string>,\n defaultExportName: string | null\n): ChunkMetadata {\n const metadata: ChunkMetadata = {\n isExported: exportedNames.has(name) || defaultExportName === name,\n isDefaultExport: defaultExportName === name,\n };\n\n // Extract props from parameters\n const params = node.params;\n if (params.length > 0) {\n const firstParam = params[0];\n const props = extractPropsFromParam(firstParam);\n if (props.length > 0) {\n metadata.props = props;\n }\n }\n\n // Extract hooks and JSX elements\n const hooks: string[] = [];\n const jsxElements: string[] = [];\n\n function searchForHooksAndJSX(n: TSESTree.Node) {\n // Find hook calls\n if (\n n.type === AST_NODE_TYPES.CallExpression &&\n n.callee.type === AST_NODE_TYPES.Identifier &&\n /^use[A-Z]/.test(n.callee.name)\n ) {\n hooks.push(n.callee.name);\n }\n\n // Find JSX elements\n if (n.type === AST_NODE_TYPES.JSXOpeningElement) {\n if (n.name.type === AST_NODE_TYPES.JSXIdentifier) {\n jsxElements.push(n.name.name);\n } else if (n.name.type === AST_NODE_TYPES.JSXMemberExpression) {\n // Handle React.Fragment, etc.\n const parts: string[] = [];\n let current: TSESTree.JSXMemberExpression | TSESTree.JSXIdentifier = n.name;\n while (current.type === AST_NODE_TYPES.JSXMemberExpression) {\n if (current.property.type === AST_NODE_TYPES.JSXIdentifier) {\n parts.unshift(current.property.name);\n }\n current = current.object as TSESTree.JSXMemberExpression | TSESTree.JSXIdentifier;\n }\n if (current.type === AST_NODE_TYPES.JSXIdentifier) {\n parts.unshift(current.name);\n }\n jsxElements.push(parts.join(\".\"));\n }\n }\n\n // Recurse\n for (const key of Object.keys(n)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (n as unknown as Record<string, unknown>)[key];\n if (child && typeof child === \"object\") {\n if (Array.isArray(child)) {\n child.forEach((c) => {\n if (c && typeof c === \"object\" && \"type\" in c) {\n searchForHooksAndJSX(c as TSESTree.Node);\n }\n });\n } else if (\"type\" in child) {\n searchForHooksAndJSX(child as TSESTree.Node);\n }\n }\n }\n }\n\n searchForHooksAndJSX(node);\n\n if (hooks.length > 0) {\n metadata.hooks = [...new Set(hooks)]; // Deduplicate\n }\n if (jsxElements.length > 0) {\n metadata.jsxElements = [...new Set(jsxElements)]; // Deduplicate\n }\n\n return metadata;\n}\n\nfunction extractPropsFromParam(param: TSESTree.Parameter): string[] {\n const props: string[] = [];\n\n if (param.type === AST_NODE_TYPES.ObjectPattern) {\n for (const prop of param.properties) {\n if (prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier) {\n props.push(prop.key.name);\n } else if (\n prop.type === AST_NODE_TYPES.RestElement &&\n prop.argument.type === AST_NODE_TYPES.Identifier\n ) {\n props.push(`...${prop.argument.name}`);\n }\n }\n } else if (param.type === AST_NODE_TYPES.Identifier) {\n props.push(param.name);\n }\n\n return props;\n}\n\nfunction getDeclarationNames(\n decl:\n | TSESTree.FunctionDeclaration\n | TSESTree.VariableDeclaration\n | TSESTree.ClassDeclaration\n | TSESTree.TSInterfaceDeclaration\n | TSESTree.TSTypeAliasDeclaration\n | TSESTree.TSEnumDeclaration\n | TSESTree.TSModuleDeclaration\n | TSESTree.TSDeclareFunction\n | TSESTree.TSImportEqualsDeclaration\n): string[] {\n const names: string[] = [];\n\n if (decl.type === AST_NODE_TYPES.FunctionDeclaration && decl.id) {\n names.push(decl.id.name);\n } else if (decl.type === AST_NODE_TYPES.VariableDeclaration) {\n for (const d of decl.declarations) {\n if (d.id.type === AST_NODE_TYPES.Identifier) {\n names.push(d.id.name);\n }\n }\n } else if (decl.type === AST_NODE_TYPES.ClassDeclaration && decl.id) {\n names.push(decl.id.name);\n }\n\n return names;\n}\n\nfunction shouldIncludeChunk(\n chunk: CodeChunk,\n minLines: number,\n includeAnonymous: boolean,\n kinds?: ChunkKind[]\n): boolean {\n const lineCount = chunk.endLine - chunk.startLine + 1;\n if (lineCount < minLines) {\n return false;\n }\n if (!includeAnonymous && chunk.name === null) {\n return false;\n }\n if (kinds && !kinds.includes(chunk.kind)) {\n return false;\n }\n return true;\n}\n\n/** Maximum characters for embedding input (safe limit for nomic-embed-text with 2048 token context) */\nconst DEFAULT_MAX_EMBEDDING_CHARS = 6000;\n\nexport interface EmbeddingInputOptions {\n /** Maximum characters for the embedding input (default: 6000) */\n maxChars?: number;\n}\n\n/**\n * Prepare chunk content for embedding by enriching with context\n */\nexport function prepareEmbeddingInput(\n chunk: CodeChunk,\n options: EmbeddingInputOptions = {}\n): string {\n const { maxChars = DEFAULT_MAX_EMBEDDING_CHARS } = options;\n const parts: string[] = [];\n\n // Add structural context based on kind\n if (chunk.kind === \"component\") {\n parts.push(`React component: ${chunk.name || \"anonymous\"}`);\n if (chunk.metadata.props?.length) {\n parts.push(`Props: ${chunk.metadata.props.join(\", \")}`);\n }\n } else if (chunk.kind === \"component-summary\") {\n parts.push(`React component summary: ${chunk.name || \"anonymous\"}`);\n if (chunk.metadata.props?.length) {\n parts.push(`Props: ${chunk.metadata.props.join(\", \")}`);\n }\n parts.push(\"(Large component - see sections for JSX details)\");\n } else if (chunk.kind === \"jsx-section\") {\n const parentName = chunk.name || \"anonymous\";\n const label = chunk.sectionLabel || `section-${chunk.sectionIndex}`;\n parts.push(`JSX section from ${parentName}: ${label}`);\n } else if (chunk.kind === \"hook\") {\n parts.push(`React hook: ${chunk.name || \"anonymous\"}`);\n } else if (chunk.kind === \"function\") {\n parts.push(`Function: ${chunk.name || \"anonymous\"}`);\n } else if (chunk.kind === \"function-summary\") {\n parts.push(`Function summary: ${chunk.name || \"anonymous\"}`);\n parts.push(\"(Large function - split into sections)\");\n } else if (chunk.kind === \"function-section\") {\n const parentName = chunk.name || \"anonymous\";\n const label = chunk.sectionLabel || `section-${chunk.sectionIndex}`;\n parts.push(`Function section from ${parentName}: ${label}`);\n } else if (chunk.kind === \"jsx-fragment\") {\n parts.push(`JSX fragment: ${chunk.name || \"anonymous\"}`);\n }\n\n // Add the code\n parts.push(chunk.content);\n\n // Add JSX structure for components\n if (chunk.metadata.jsxElements?.length) {\n parts.push(`JSX elements: ${chunk.metadata.jsxElements.join(\", \")}`);\n }\n\n // Add hooks used\n if (chunk.metadata.hooks?.length) {\n parts.push(`Hooks used: ${chunk.metadata.hooks.join(\", \")}`);\n }\n\n let result = parts.join(\"\\n\\n\");\n\n // Truncate if exceeds max chars (safety net for edge cases)\n if (result.length > maxChars) {\n result = result.slice(0, maxChars - 50) + \"\\n\\n[... content truncated for embedding ...]\";\n }\n\n return result;\n}\n\n// ============================================================================\n// Large Component Splitting\n// ============================================================================\n\n/**\n * Split a large chunk into smaller chunks\n * For components, tries JSX-based splitting first, then falls back to line-based\n * For functions/hooks, uses line-based splitting\n */\nfunction splitLargeChunk(\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,\n originalChunk: CodeChunk,\n content: string,\n lines: string[],\n maxLines: number,\n strategy: \"jsx-children\" | \"line-based\"\n): CodeChunk[] {\n // Only try JSX splitting for components\n if (strategy === \"jsx-children\" && originalChunk.kind === \"component\") {\n const jsxChunks = splitByJSXChildren(node, originalChunk, content, lines);\n if (jsxChunks.length > 0) {\n return jsxChunks;\n }\n // Fall back to line-based if no JSX children found\n }\n\n return splitByLines(originalChunk, lines, maxLines);\n}\n\n/**\n * Split a component by its top-level JSX children\n */\nfunction splitByJSXChildren(\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,\n originalChunk: CodeChunk,\n content: string,\n lines: string[]\n): CodeChunk[] {\n // Find the return statement with JSX\n const returnStatement = findJSXReturnStatement(node);\n if (!returnStatement || !returnStatement.argument) {\n return [];\n }\n\n // Get the root JSX element\n const jsxRoot = getJSXRoot(returnStatement.argument);\n if (!jsxRoot) {\n return [];\n }\n\n // Get significant JSX children\n const children = getSignificantJSXChildren(jsxRoot);\n if (children.length < 2) {\n // Not worth splitting if there's only one child\n return [];\n }\n\n const chunks: CodeChunk[] = [];\n\n // Create a summary chunk (signature + hooks + state, without the full JSX)\n const summaryChunk = createSummaryChunk(node, originalChunk, returnStatement, lines);\n chunks.push(summaryChunk);\n\n // Create section chunks for each significant JSX child\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n const sectionChunk = createJSXSectionChunk(\n originalChunk,\n child,\n lines,\n i,\n summaryChunk.id\n );\n if (sectionChunk) {\n chunks.push(sectionChunk);\n }\n }\n\n return chunks;\n}\n\n/**\n * Find the return statement containing JSX\n */\nfunction findJSXReturnStatement(\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression\n): TSESTree.ReturnStatement | null {\n // For arrow functions with expression body, create a synthetic return\n if (node.type === AST_NODE_TYPES.ArrowFunctionExpression && node.expression) {\n if (isJSXNode(node.body)) {\n return {\n type: AST_NODE_TYPES.ReturnStatement,\n argument: node.body as TSESTree.Expression,\n loc: node.body.loc,\n range: node.body.range,\n parent: node as unknown as TSESTree.Node,\n } as TSESTree.ReturnStatement;\n }\n return null;\n }\n\n // For function bodies, find the return statement\n const body = node.body;\n if (body.type !== AST_NODE_TYPES.BlockStatement) {\n return null;\n }\n\n // Look for return statements in the body (not nested in other blocks)\n for (const stmt of body.body) {\n if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument && isJSXNode(stmt.argument)) {\n return stmt;\n }\n }\n\n return null;\n}\n\n/**\n * Check if a node is a JSX element or fragment\n */\nfunction isJSXNode(node: TSESTree.Node): boolean {\n return (\n node.type === AST_NODE_TYPES.JSXElement ||\n node.type === AST_NODE_TYPES.JSXFragment\n );\n}\n\n/**\n * Get the root JSX element, unwrapping parentheses and fragments if needed\n */\nfunction getJSXRoot(\n node: TSESTree.Expression\n): TSESTree.JSXElement | TSESTree.JSXFragment | null {\n // Handle parenthesized expressions\n if (node.type === AST_NODE_TYPES.JSXElement) {\n return node;\n }\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return node;\n }\n return null;\n}\n\n/**\n * Get significant JSX children (skip whitespace-only text nodes)\n */\nfunction getSignificantJSXChildren(\n jsxRoot: TSESTree.JSXElement | TSESTree.JSXFragment\n): TSESTree.JSXChild[] {\n const children: TSESTree.JSXChild[] = [];\n\n for (const child of jsxRoot.children) {\n // Skip JSXText that's just whitespace\n if (child.type === AST_NODE_TYPES.JSXText) {\n if (child.value.trim() === \"\") {\n continue;\n }\n }\n\n // Include JSX elements, expressions, and non-empty text\n if (\n child.type === AST_NODE_TYPES.JSXElement ||\n child.type === AST_NODE_TYPES.JSXFragment ||\n child.type === AST_NODE_TYPES.JSXExpressionContainer\n ) {\n children.push(child);\n }\n }\n\n return children;\n}\n\n/**\n * Create a summary chunk containing function signature, hooks, and state\n */\nfunction createSummaryChunk(\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,\n originalChunk: CodeChunk,\n returnStatement: TSESTree.ReturnStatement,\n lines: string[]\n): CodeChunk {\n // Get lines from function start to just before the return statement\n const startLine = originalChunk.startLine;\n const returnLine = returnStatement.loc?.start.line || originalChunk.endLine;\n\n // Include the first line of the return (e.g., \"return (\") but not the JSX body\n const summaryEndLine = Math.min(returnLine, originalChunk.endLine);\n\n // Extract the summary content\n const summaryLines = lines.slice(startLine - 1, summaryEndLine);\n\n // Add closing brace to make it syntactically valid-ish\n const summaryContent = summaryLines.join(\"\\n\") + \"\\n // ... JSX content (see sections)\\n );\";\n\n return {\n id: hashChunk(summaryContent, originalChunk.filePath, startLine),\n filePath: originalChunk.filePath,\n startLine: startLine,\n endLine: summaryEndLine,\n startColumn: originalChunk.startColumn,\n endColumn: originalChunk.endColumn,\n kind: \"component-summary\",\n name: originalChunk.name,\n content: summaryContent,\n metadata: {\n ...originalChunk.metadata,\n // Keep hooks but clear JSX elements (they're in the sections)\n jsxElements: undefined,\n },\n };\n}\n\n/**\n * Create a JSX section chunk from a JSX child element\n */\nfunction createJSXSectionChunk(\n originalChunk: CodeChunk,\n jsxChild: TSESTree.JSXChild,\n lines: string[],\n index: number,\n parentId: string\n): CodeChunk | null {\n const loc = jsxChild.loc;\n if (!loc) {\n return null;\n }\n\n const startLine = loc.start.line;\n const endLine = loc.end.line;\n const lineCount = endLine - startLine + 1;\n\n // Skip very small sections\n if (lineCount < MIN_SECTION_LINES) {\n return null;\n }\n\n // Extract the content\n const sectionContent = lines.slice(startLine - 1, endLine).join(\"\\n\");\n\n // Infer a label from the JSX element\n const label = inferSectionLabel(jsxChild, index);\n\n // Extract JSX elements in this section\n const jsxElements = extractJSXElementsFromNode(jsxChild);\n\n return {\n id: hashChunk(sectionContent, originalChunk.filePath, startLine),\n filePath: originalChunk.filePath,\n startLine,\n endLine,\n startColumn: loc.start.column,\n endColumn: loc.end.column,\n kind: \"jsx-section\",\n name: originalChunk.name,\n content: sectionContent,\n metadata: {\n jsxElements: jsxElements.length > 0 ? jsxElements : undefined,\n isExported: originalChunk.metadata.isExported,\n isDefaultExport: originalChunk.metadata.isDefaultExport,\n },\n parentId,\n sectionIndex: index,\n sectionLabel: label,\n };\n}\n\n/**\n * Infer a human-readable label for a JSX section\n */\nfunction inferSectionLabel(jsxChild: TSESTree.JSXChild, index: number): string {\n if (jsxChild.type === AST_NODE_TYPES.JSXElement) {\n const opening = jsxChild.openingElement;\n\n // Try to get a meaningful name from attributes\n for (const attr of opening.attributes) {\n if (attr.type === AST_NODE_TYPES.JSXAttribute && attr.name.type === AST_NODE_TYPES.JSXIdentifier) {\n const attrName = attr.name.name;\n\n // Look for common identifying attributes\n if (attrName === \"aria-label\" || attrName === \"aria-labelledby\") {\n if (attr.value?.type === AST_NODE_TYPES.Literal && typeof attr.value.value === \"string\") {\n return attr.value.value.toLowerCase().replace(/\\s+/g, \"-\").slice(0, 30);\n }\n }\n\n // Check className for semantic hints\n if (attrName === \"className\" || attrName === \"class\") {\n if (attr.value?.type === AST_NODE_TYPES.Literal && typeof attr.value.value === \"string\") {\n const className = attr.value.value;\n // Extract first meaningful class\n const classes = className.split(/\\s+/);\n for (const cls of classes) {\n // Skip utility classes (Tailwind patterns)\n if (!cls.match(/^(bg-|text-|p-|m-|w-|h-|flex|grid|border|rounded|shadow|hover:|focus:)/)) {\n return cls.slice(0, 30);\n }\n }\n }\n }\n }\n }\n\n // Fall back to element name\n if (opening.name.type === AST_NODE_TYPES.JSXIdentifier) {\n return `${opening.name.name}-${index}`;\n }\n }\n\n return `section-${index}`;\n}\n\n/**\n * Extract JSX element names from a node\n */\nfunction extractJSXElementsFromNode(node: TSESTree.Node): string[] {\n const elements: string[] = [];\n\n function search(n: TSESTree.Node) {\n if (n.type === AST_NODE_TYPES.JSXOpeningElement) {\n if (n.name.type === AST_NODE_TYPES.JSXIdentifier) {\n elements.push(n.name.name);\n } else if (n.name.type === AST_NODE_TYPES.JSXMemberExpression) {\n const parts: string[] = [];\n let current: TSESTree.JSXMemberExpression | TSESTree.JSXIdentifier = n.name;\n while (current.type === AST_NODE_TYPES.JSXMemberExpression) {\n if (current.property.type === AST_NODE_TYPES.JSXIdentifier) {\n parts.unshift(current.property.name);\n }\n current = current.object as TSESTree.JSXMemberExpression | TSESTree.JSXIdentifier;\n }\n if (current.type === AST_NODE_TYPES.JSXIdentifier) {\n parts.unshift(current.name);\n }\n elements.push(parts.join(\".\"));\n }\n }\n\n // Recurse\n for (const key of Object.keys(n)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (n as unknown as Record<string, unknown>)[key];\n if (child && typeof child === \"object\") {\n if (Array.isArray(child)) {\n child.forEach((c) => {\n if (c && typeof c === \"object\" && \"type\" in c) {\n search(c as TSESTree.Node);\n }\n });\n } else if (\"type\" in child) {\n search(child as TSESTree.Node);\n }\n }\n }\n }\n\n search(node);\n return [...new Set(elements)];\n}\n\n/**\n * Split a chunk by line count (fallback strategy)\n */\nfunction splitByLines(\n originalChunk: CodeChunk,\n lines: string[],\n maxLines: number\n): CodeChunk[] {\n const totalLines = originalChunk.endLine - originalChunk.startLine + 1;\n\n // If it fits, return as-is\n if (totalLines <= maxLines) {\n return [originalChunk];\n }\n\n // Determine the appropriate kinds based on original chunk type\n const isComponent = originalChunk.kind === \"component\" || originalChunk.kind === \"jsx-fragment\";\n const summaryKind: ChunkKind = isComponent ? \"component-summary\" : \"function-summary\";\n const sectionKind: ChunkKind = isComponent ? \"jsx-section\" : \"function-section\";\n\n const chunks: CodeChunk[] = [];\n const overlap = Math.min(10, Math.floor(maxLines / 5)); // 10 lines overlap, or 20% of maxLines\n\n let currentStart = originalChunk.startLine;\n let sectionIndex = 0;\n\n while (currentStart <= originalChunk.endLine) {\n const currentEnd = Math.min(currentStart + maxLines - 1, originalChunk.endLine);\n const sectionContent = lines.slice(currentStart - 1, currentEnd).join(\"\\n\");\n\n const isFirstSection = sectionIndex === 0;\n\n chunks.push({\n id: hashChunk(sectionContent, originalChunk.filePath, currentStart),\n filePath: originalChunk.filePath,\n startLine: currentStart,\n endLine: currentEnd,\n startColumn: isFirstSection ? originalChunk.startColumn : 0,\n endColumn: currentEnd === originalChunk.endLine ? originalChunk.endColumn : lines[currentEnd - 1]?.length || 0,\n kind: isFirstSection ? summaryKind : sectionKind,\n name: originalChunk.name,\n content: sectionContent,\n metadata: isFirstSection ? originalChunk.metadata : {\n isExported: originalChunk.metadata.isExported,\n isDefaultExport: originalChunk.metadata.isDefaultExport,\n },\n parentId: isFirstSection ? undefined : chunks[0]?.id,\n sectionIndex: isFirstSection ? undefined : sectionIndex,\n sectionLabel: isFirstSection ? undefined : `lines-${currentStart}-${currentEnd}`,\n });\n\n // Move to next section with overlap\n currentStart = currentEnd - overlap + 1;\n sectionIndex++;\n\n // Prevent infinite loop\n if (currentStart <= originalChunk.startLine + sectionIndex * (maxLines - overlap)) {\n currentStart = originalChunk.startLine + sectionIndex * (maxLines - overlap);\n }\n }\n\n return chunks;\n}\n","/**\n * Ollama Embedding Client\n *\n * Uses Ollama's /api/embed endpoint to generate text embeddings.\n * Follows the patterns from uilint-core's OllamaClient.\n */\n\nconst DEFAULT_BASE_URL = \"http://localhost:11434\";\nconst DEFAULT_MODEL = \"nomic-embed-text\";\nconst DEFAULT_TIMEOUT = 60000;\nconst DEFAULT_BATCH_SIZE = 10;\n\nexport interface EmbeddingOptions {\n /** Ollama embedding model (default: nomic-embed-text) */\n model?: string;\n /** Ollama server URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Request timeout in ms (default: 60000) */\n timeout?: number;\n /** Batch size for embedding multiple texts (default: 10) */\n batchSize?: number;\n}\n\nexport interface EmbeddingResult {\n /** The embedding vector */\n embedding: number[];\n /** The model used */\n model: string;\n /** Number of tokens in the input (if available) */\n promptTokens?: number;\n}\n\nexport class OllamaEmbeddingClient {\n private baseUrl: string;\n private model: string;\n private timeout: number;\n private batchSize: number;\n\n constructor(options: EmbeddingOptions = {}) {\n this.baseUrl = options.baseUrl || DEFAULT_BASE_URL;\n this.model = options.model || DEFAULT_MODEL;\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n this.batchSize = options.batchSize || DEFAULT_BATCH_SIZE;\n }\n\n /**\n * Generate embedding for a single text\n */\n async embed(text: string): Promise<EmbeddingResult> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/embed`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n input: text,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Ollama API error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json();\n\n // Ollama returns embeddings in an array even for single input\n const embedding = data.embeddings?.[0] || data.embedding;\n\n if (!embedding || !Array.isArray(embedding)) {\n throw new Error(\"Invalid embedding response from Ollama\");\n }\n\n return {\n embedding,\n model: this.model,\n promptTokens: data.prompt_eval_count,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Generate embeddings for multiple texts\n * Automatically batches large inputs\n */\n async embedBatch(texts: string[]): Promise<EmbeddingResult[]> {\n if (texts.length === 0) {\n return [];\n }\n\n // If small enough, embed all at once\n if (texts.length <= this.batchSize) {\n return this.embedBatchDirect(texts);\n }\n\n // Otherwise, process in batches\n const results: EmbeddingResult[] = [];\n for (let i = 0; i < texts.length; i += this.batchSize) {\n const batch = texts.slice(i, i + this.batchSize);\n const batchResults = await this.embedBatchDirect(batch);\n results.push(...batchResults);\n }\n return results;\n }\n\n /**\n * Embed a batch directly (no chunking)\n */\n private async embedBatchDirect(texts: string[]): Promise<EmbeddingResult[]> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/embed`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n input: texts,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Ollama API error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json();\n const embeddings: number[][] = data.embeddings;\n\n if (!embeddings || !Array.isArray(embeddings)) {\n throw new Error(\"Invalid batch embedding response from Ollama\");\n }\n\n return embeddings.map((embedding) => ({\n embedding,\n model: this.model,\n }));\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Check if Ollama is available\n */\n async isAvailable(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/api/tags`, {\n method: \"GET\",\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /**\n * Check if the embedding model is available\n */\n async isModelAvailable(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/api/tags`, {\n method: \"GET\",\n signal: AbortSignal.timeout(5000),\n });\n\n if (!response.ok) return false;\n\n const data = await response.json();\n const models = data.models || [];\n\n return models.some(\n (m: { name: string }) =>\n m.name === this.model || m.name.startsWith(`${this.model}:`)\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Pull the embedding model if not available\n */\n async ensureModel(): Promise<void> {\n const available = await this.isModelAvailable();\n if (available) return;\n\n console.log(`Pulling embedding model ${this.model}...`);\n\n const response = await fetch(`${this.baseUrl}/api/pull`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model: this.model,\n stream: false,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to pull model ${this.model}: ${errorText}`);\n }\n }\n\n /**\n * Get the embedding dimension for the current model\n * (Requires generating a test embedding)\n */\n async getEmbeddingDimension(): Promise<number> {\n const result = await this.embed(\"test\");\n return result.embedding.length;\n }\n\n /**\n * Get the current model name\n */\n getModel(): string {\n return this.model;\n }\n\n /**\n * Set the model name\n */\n setModel(model: string): void {\n this.model = model;\n }\n}\n\n// Default singleton instance\nlet defaultClient: OllamaEmbeddingClient | null = null;\n\nexport function getOllamaEmbeddingClient(\n options?: EmbeddingOptions\n): OllamaEmbeddingClient {\n if (!defaultClient || options) {\n defaultClient = new OllamaEmbeddingClient(options);\n }\n return defaultClient;\n}\n","/**\n * Query API for semantic duplicate detection\n *\n * High-level API for indexing, finding duplicates, and semantic search.\n */\n\nimport { dirname, resolve } from \"path\";\nimport type { CodeChunk, ChunkKind } from \"../embeddings/types.js\";\nimport type { StoredChunkMetadata } from \"../index/types.js\";\nimport {\n IncrementalIndexer,\n createIndexer,\n type IndexerOptions,\n type IndexUpdateResult,\n} from \"../cache/incremental-indexer.js\";\nimport {\n findDuplicateGroups,\n findSimilarToLocation,\n findSimilarToQuery,\n type DuplicateGroup as InternalDuplicateGroup,\n type DuplicateMember,\n} from \"../detection/duplicate-finder.js\";\nimport { OllamaEmbeddingClient } from \"../embeddings/ollama-embeddings.js\";\n\nexport interface IndexOptions {\n /** Embedding model to use */\n model?: string;\n /** Ollama server URL */\n baseUrl?: string;\n /** Glob patterns to exclude */\n exclude?: string[];\n /** Force reindex from scratch */\n force?: boolean;\n /** Progress callback */\n onProgress?: (message: string, current?: number, total?: number) => void;\n}\n\nexport interface FindDuplicatesOptions {\n /** Path to search (defaults to current directory) */\n path?: string;\n /** Minimum similarity threshold (0-1). Default: 0.85 */\n threshold?: number;\n /** Minimum group size. Default: 2 */\n minGroupSize?: number;\n /** Filter by kind: component, hook, function */\n kind?: ChunkKind;\n}\n\nexport interface SearchOptions {\n /** Path to search (defaults to current directory) */\n path?: string;\n /** Number of results to return. Default: 10 */\n top?: number;\n /** Minimum similarity threshold. Default: 0.5 */\n threshold?: number;\n /** Embedding model to use */\n model?: string;\n /** Ollama server URL */\n baseUrl?: string;\n}\n\nexport interface SimilarLocationOptions extends SearchOptions {\n /** File path containing the code */\n filePath: string;\n /** Line number in the file */\n line: number;\n}\n\nexport interface DuplicateGroupMember {\n /** File path */\n filePath: string;\n /** Start line */\n startLine: number;\n /** End line */\n endLine: number;\n /** Chunk name (component/function/hook name) */\n name: string | null;\n /** Kind of code */\n kind: ChunkKind;\n /** Similarity score (1.0 for the reference member) */\n score: number;\n}\n\nexport interface DuplicateGroup {\n /** Members of the duplicate group */\n members: DuplicateGroupMember[];\n /** Average similarity between all group members */\n avgSimilarity: number;\n /** The kind of code in this group */\n kind: ChunkKind;\n}\n\nexport interface SearchResult {\n /** File path */\n filePath: string;\n /** Start line */\n startLine: number;\n /** End line */\n endLine: number;\n /** Chunk name */\n name: string | null;\n /** Kind of code */\n kind: ChunkKind;\n /** Similarity score */\n score: number;\n}\n\n// Cache for loaded indexers to avoid reloading on every query\nconst indexerCache = new Map<string, IncrementalIndexer>();\n\n/**\n * Get or create an indexer for a project path.\n */\nfunction getIndexer(path: string, options?: IndexerOptions): IncrementalIndexer {\n const projectRoot = resolve(path);\n const cacheKey = projectRoot;\n\n let indexer = indexerCache.get(cacheKey);\n if (!indexer) {\n indexer = createIndexer(projectRoot, options);\n indexerCache.set(cacheKey, indexer);\n }\n\n return indexer;\n}\n\n/**\n * Clear the indexer cache for a path.\n */\nexport function clearIndexerCache(path?: string): void {\n if (path) {\n const projectRoot = resolve(path);\n indexerCache.delete(projectRoot);\n } else {\n indexerCache.clear();\n }\n}\n\n/**\n * Index a directory for semantic duplicate detection.\n * Creates or updates the index at .uilint/.duplicates-index/\n */\nexport async function indexDirectory(\n path: string,\n options: IndexOptions = {}\n): Promise<IndexUpdateResult> {\n const projectRoot = resolve(path);\n\n // Clear cache to ensure fresh indexer\n clearIndexerCache(projectRoot);\n\n const indexer = createIndexer(projectRoot, {\n model: options.model,\n baseUrl: options.baseUrl,\n exclude: options.exclude,\n onProgress: options.onProgress,\n });\n\n // Update cache\n indexerCache.set(projectRoot, indexer);\n\n if (options.force) {\n return await indexer.indexAll(true);\n }\n\n // Try incremental update first, fall back to full index\n if (indexer.hasIndex()) {\n return await indexer.update();\n }\n\n return await indexer.indexAll(false);\n}\n\n/**\n * Find semantic duplicate groups in the indexed codebase.\n */\nexport async function findDuplicates(\n options: FindDuplicatesOptions = {}\n): Promise<DuplicateGroup[]> {\n const projectRoot = resolve(options.path || process.cwd());\n const indexer = getIndexer(projectRoot);\n\n // Load the index\n await indexer.load();\n\n if (!indexer.hasIndex()) {\n throw new Error(\n `No index found at ${projectRoot}. Run 'uilint duplicates index' first.`\n );\n }\n\n const vectorStore = indexer.getVectorStore();\n const metadataStore = indexer.getMetadataStore();\n\n const groups = findDuplicateGroups(vectorStore, metadataStore, {\n threshold: options.threshold,\n minGroupSize: options.minGroupSize,\n kind: options.kind,\n });\n\n // Transform to public API format\n return groups.map((group) => ({\n members: group.members.map((m) => ({\n filePath: m.metadata.filePath,\n startLine: m.metadata.startLine,\n endLine: m.metadata.endLine,\n name: m.metadata.name,\n kind: m.metadata.kind,\n score: m.score,\n })),\n avgSimilarity: group.avgSimilarity,\n kind: group.kind,\n }));\n}\n\n/**\n * Search for code semantically similar to a text query.\n */\nexport async function searchSimilar(\n query: string,\n options: SearchOptions = {}\n): Promise<SearchResult[]> {\n const projectRoot = resolve(options.path || process.cwd());\n const indexer = getIndexer(projectRoot);\n\n // Load the index\n await indexer.load();\n\n if (!indexer.hasIndex()) {\n throw new Error(\n `No index found at ${projectRoot}. Run 'uilint duplicates index' first.`\n );\n }\n\n // Create embedding client\n const embeddingClient = new OllamaEmbeddingClient({\n model: options.model,\n baseUrl: options.baseUrl,\n });\n\n // Embed the query\n const queryResult = await embeddingClient.embed(query);\n\n const vectorStore = indexer.getVectorStore();\n const metadataStore = indexer.getMetadataStore();\n\n const results = findSimilarToQuery(vectorStore, queryResult.embedding, {\n top: options.top,\n threshold: options.threshold,\n });\n\n // Transform to public API format\n return results\n .map((r) => {\n const metadata = metadataStore.get(r.id);\n if (!metadata) return null;\n return {\n filePath: metadata.filePath,\n startLine: metadata.startLine,\n endLine: metadata.endLine,\n name: metadata.name,\n kind: metadata.kind,\n score: r.score,\n };\n })\n .filter((r): r is SearchResult => r !== null);\n}\n\n/**\n * Find code similar to a specific location (file:line).\n */\nexport async function findSimilarAtLocation(\n options: SimilarLocationOptions\n): Promise<SearchResult[]> {\n const projectRoot = resolve(options.path || process.cwd());\n const indexer = getIndexer(projectRoot);\n\n // Load the index\n await indexer.load();\n\n if (!indexer.hasIndex()) {\n throw new Error(\n `No index found at ${projectRoot}. Run 'uilint duplicates index' first.`\n );\n }\n\n const vectorStore = indexer.getVectorStore();\n const metadataStore = indexer.getMetadataStore();\n\n const results = findSimilarToLocation(\n vectorStore,\n metadataStore,\n options.filePath,\n options.line,\n {\n top: options.top,\n threshold: options.threshold,\n }\n );\n\n // Transform to public API format\n return results\n .map((r) => {\n const metadata = metadataStore.get(r.id);\n if (!metadata) return null;\n return {\n filePath: metadata.filePath,\n startLine: metadata.startLine,\n endLine: metadata.endLine,\n name: metadata.name,\n kind: metadata.kind,\n score: r.score,\n };\n })\n .filter((r): r is SearchResult => r !== null);\n}\n\n/**\n * Check if an index exists for the given path.\n */\nexport function hasIndex(path: string = process.cwd()): boolean {\n const projectRoot = resolve(path);\n const indexer = getIndexer(projectRoot);\n return indexer.hasIndex();\n}\n\n/**\n * Get index statistics.\n */\nexport async function getIndexStats(path: string = process.cwd()): Promise<{\n totalFiles: number;\n totalChunks: number;\n indexSizeBytes: number;\n embeddingModel: string | null;\n lastUpdated: string | null;\n}> {\n const projectRoot = resolve(path);\n const indexer = getIndexer(projectRoot);\n\n await indexer.load();\n\n const stats = indexer.getStats();\n return {\n totalFiles: stats.totalFiles,\n totalChunks: stats.totalChunks,\n indexSizeBytes: stats.indexSizeBytes,\n embeddingModel: stats.manifest?.embeddingModel || null,\n lastUpdated: stats.manifest?.updatedAt || null,\n };\n}\n","/**\n * Incremental Indexer\n *\n * Combines chunker, embedding client, and storage to build and update\n * the semantic index incrementally.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join, relative } from \"path\";\nimport { glob } from \"glob\";\nimport { chunkFile, prepareEmbeddingInput } from \"../embeddings/chunker.js\";\nimport {\n OllamaEmbeddingClient,\n type EmbeddingOptions,\n} from \"../embeddings/ollama-embeddings.js\";\nimport { VectorStore } from \"../index/vector-store.js\";\nimport { MetadataStore } from \"../index/metadata-store.js\";\nimport {\n FileTracker,\n hashContentSync,\n type FileChange,\n} from \"./file-tracker.js\";\nimport type { ChunkingOptions } from \"../embeddings/types.js\";\nimport type { IndexManifest, StoredChunkMetadata } from \"../index/types.js\";\n\nconst INDEX_DIR = \".uilint/.duplicates-index\";\nconst MANIFEST_FILE = \"manifest.json\";\nconst MANIFEST_VERSION = 1;\n\nexport interface IndexerOptions {\n /** Embedding model to use */\n model?: string;\n /** Ollama server URL */\n baseUrl?: string;\n /** Glob patterns to include (default: **\\/*.{ts,tsx,js,jsx}) */\n include?: string[];\n /** Glob patterns to exclude */\n exclude?: string[];\n /** Chunking options */\n chunking?: ChunkingOptions;\n /** Progress callback */\n onProgress?: (message: string, current?: number, total?: number) => void;\n}\n\nexport interface IndexUpdateResult {\n /** Number of files added */\n added: number;\n /** Number of files modified */\n modified: number;\n /** Number of files deleted */\n deleted: number;\n /** Total chunks in index */\n totalChunks: number;\n /** Duration in milliseconds */\n duration: number;\n}\n\nexport class IncrementalIndexer {\n private vectorStore: VectorStore;\n private metadataStore: MetadataStore;\n private fileTracker: FileTracker;\n private embeddingClient: OllamaEmbeddingClient;\n private projectRoot: string;\n private indexDir: string;\n private options: IndexerOptions;\n private manifest: IndexManifest | null = null;\n\n constructor(projectRoot: string, options: IndexerOptions = {}) {\n this.projectRoot = projectRoot;\n this.indexDir = join(projectRoot, INDEX_DIR);\n this.options = options;\n\n this.vectorStore = new VectorStore();\n this.metadataStore = new MetadataStore();\n this.fileTracker = new FileTracker();\n this.embeddingClient = new OllamaEmbeddingClient({\n model: options.model,\n baseUrl: options.baseUrl,\n });\n }\n\n /**\n * Get the include patterns\n */\n private getIncludePatterns(): string[] {\n return this.options.include || [\"**/*.{ts,tsx,js,jsx}\"];\n }\n\n /**\n * Get the exclude patterns\n */\n private getExcludePatterns(): string[] {\n return [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.git/**\",\n \"**/*.test.{ts,tsx,js,jsx}\",\n \"**/*.spec.{ts,tsx,js,jsx}\",\n \"**/__tests__/**\",\n ...(this.options.exclude || []),\n ];\n }\n\n /**\n * Find all files to index\n */\n private async findFiles(): Promise<string[]> {\n const files: string[] = [];\n\n for (const pattern of this.getIncludePatterns()) {\n const matches = await glob(pattern, {\n cwd: this.projectRoot,\n ignore: this.getExcludePatterns(),\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n return [...new Set(files)]; // Dedupe\n }\n\n /**\n * Load existing index from disk\n */\n async load(): Promise<void> {\n if (!existsSync(this.indexDir)) {\n return;\n }\n\n try {\n // Load manifest\n const manifestPath = join(this.indexDir, MANIFEST_FILE);\n if (existsSync(manifestPath)) {\n const content = readFileSync(manifestPath, \"utf-8\");\n this.manifest = JSON.parse(content);\n }\n\n // Load stores\n await this.vectorStore.load(this.indexDir);\n await this.metadataStore.load(this.indexDir);\n await this.fileTracker.load(this.indexDir);\n } catch (error) {\n // If loading fails, start fresh\n this.vectorStore = new VectorStore();\n this.metadataStore = new MetadataStore();\n this.fileTracker = new FileTracker();\n this.manifest = null;\n }\n }\n\n /**\n * Save index to disk\n */\n async save(): Promise<void> {\n if (!existsSync(this.indexDir)) {\n mkdirSync(this.indexDir, { recursive: true });\n }\n\n // Update and save manifest\n const now = new Date().toISOString();\n const dimension = this.vectorStore.getDimension();\n\n this.manifest = {\n version: MANIFEST_VERSION,\n createdAt: this.manifest?.createdAt || now,\n updatedAt: now,\n embeddingModel: this.embeddingClient.getModel(),\n dimension: dimension || 0,\n fileCount: this.fileTracker.getTrackedFiles().length,\n chunkCount: this.metadataStore.size(),\n };\n\n const manifestPath = join(this.indexDir, MANIFEST_FILE);\n writeFileSync(\n manifestPath,\n JSON.stringify(this.manifest, null, 2),\n \"utf-8\"\n );\n\n // Save stores\n await this.vectorStore.save(this.indexDir);\n await this.metadataStore.save(this.indexDir);\n await this.fileTracker.save(this.indexDir);\n }\n\n /**\n * Index all files from scratch\n */\n async indexAll(force: boolean = false): Promise<IndexUpdateResult> {\n const startTime = Date.now();\n const log = this.options.onProgress || (() => {});\n\n // Check if Ollama is available\n const available = await this.embeddingClient.isAvailable();\n if (!available) {\n throw new Error(\n \"Ollama is not available. Make sure it's running at \" +\n (this.options.baseUrl || \"http://localhost:11434\")\n );\n }\n\n // Clear existing index if force\n if (force) {\n this.vectorStore.clear();\n this.metadataStore.clear();\n this.fileTracker.clear();\n } else {\n await this.load();\n }\n\n // Find files\n log(\"Finding files...\");\n const files = await this.findFiles();\n log(`Found ${files.length} files`);\n\n // Detect changes\n const changes = force\n ? files.map((path) => ({ path, type: \"added\" as const, newHash: \"\" }))\n : await this.fileTracker.detectChanges(files);\n\n // Process changes\n const result = await this.processChanges(changes, log);\n\n // Save index\n log(\"Saving index...\");\n await this.save();\n\n return {\n ...result,\n duration: Date.now() - startTime,\n };\n }\n\n /**\n * Update index incrementally\n */\n async update(): Promise<IndexUpdateResult> {\n const startTime = Date.now();\n const log = this.options.onProgress || (() => {});\n\n // Load existing index\n await this.load();\n\n // Check if Ollama is available\n const available = await this.embeddingClient.isAvailable();\n if (!available) {\n throw new Error(\"Ollama is not available\");\n }\n\n // Find files and detect changes\n log(\"Detecting changes...\");\n const files = await this.findFiles();\n const changes = await this.fileTracker.detectChanges(files);\n\n if (changes.length === 0) {\n log(\"No changes detected\");\n return {\n added: 0,\n modified: 0,\n deleted: 0,\n totalChunks: this.metadataStore.size(),\n duration: Date.now() - startTime,\n };\n }\n\n log(`Found ${changes.length} changed files`);\n\n // Process changes\n const result = await this.processChanges(changes, log);\n\n // Save index\n log(\"Saving index...\");\n await this.save();\n\n return {\n ...result,\n duration: Date.now() - startTime,\n };\n }\n\n /**\n * Process file changes\n */\n private async processChanges(\n changes: FileChange[],\n log: (msg: string, current?: number, total?: number) => void\n ): Promise<Omit<IndexUpdateResult, \"duration\">> {\n let added = 0;\n let modified = 0;\n let deleted = 0;\n\n // Handle deletions first\n const deletedFiles = changes.filter((c) => c.type === \"deleted\");\n for (const change of deletedFiles) {\n const removedIds = this.metadataStore.removeByFilePath(change.path);\n for (const id of removedIds) {\n this.vectorStore.remove(id);\n }\n this.fileTracker.removeEntry(change.path);\n deleted++;\n }\n\n // Handle additions and modifications\n const filesToProcess = changes.filter((c) => c.type !== \"deleted\");\n\n for (let i = 0; i < filesToProcess.length; i++) {\n const change = filesToProcess[i];\n log(\n `Processing ${relative(this.projectRoot, change.path)}`,\n i + 1,\n filesToProcess.length\n );\n\n try {\n // Read file content\n const content = readFileSync(change.path, \"utf-8\");\n\n // Remove old chunks if modified\n if (change.type === \"modified\") {\n const removedIds = this.metadataStore.removeByFilePath(change.path);\n for (const id of removedIds) {\n this.vectorStore.remove(id);\n }\n modified++;\n } else {\n added++;\n }\n\n // Chunk the file\n const chunks = chunkFile(change.path, content, this.options.chunking);\n\n if (chunks.length === 0) {\n // No chunks to embed, but still track the file\n await this.fileTracker.updateFile(change.path, content, []);\n continue;\n }\n\n // Prepare embedding inputs\n const embeddingInputs = chunks.map((c) => prepareEmbeddingInput(c));\n\n // Generate embeddings\n const embeddings =\n await this.embeddingClient.embedBatch(embeddingInputs);\n\n // Store chunks and embeddings\n const chunkIds: string[] = [];\n for (let j = 0; j < chunks.length; j++) {\n const chunk = chunks[j];\n const embedding = embeddings[j].embedding;\n\n // Store vector\n this.vectorStore.add(chunk.id, embedding);\n\n // Store metadata\n const metadata: StoredChunkMetadata = {\n filePath: chunk.filePath,\n startLine: chunk.startLine,\n endLine: chunk.endLine,\n startColumn: chunk.startColumn,\n endColumn: chunk.endColumn,\n kind: chunk.kind,\n name: chunk.name,\n contentHash: hashContentSync(chunk.content),\n metadata: {\n props: chunk.metadata.props,\n hooks: chunk.metadata.hooks,\n jsxElements: chunk.metadata.jsxElements,\n isExported: chunk.metadata.isExported,\n isDefaultExport: chunk.metadata.isDefaultExport,\n },\n };\n this.metadataStore.set(chunk.id, metadata);\n\n chunkIds.push(chunk.id);\n }\n\n // Update file tracker\n await this.fileTracker.updateFile(change.path, content, chunkIds);\n } catch (error) {\n console.warn(`Error processing ${change.path}:`, error);\n }\n }\n\n return {\n added,\n modified,\n deleted,\n totalChunks: this.metadataStore.size(),\n };\n }\n\n /**\n * Get index statistics\n */\n getStats(): {\n totalFiles: number;\n totalChunks: number;\n indexSizeBytes: number;\n manifest: IndexManifest | null;\n } {\n return {\n totalFiles: this.fileTracker.getTrackedFiles().length,\n totalChunks: this.metadataStore.size(),\n indexSizeBytes: this.vectorStore.getStats().memoryBytes,\n manifest: this.manifest,\n };\n }\n\n /**\n * Get the vector store (for queries)\n */\n getVectorStore(): VectorStore {\n return this.vectorStore;\n }\n\n /**\n * Get the metadata store (for queries)\n */\n getMetadataStore(): MetadataStore {\n return this.metadataStore;\n }\n\n /**\n * Check if index exists\n */\n hasIndex(): boolean {\n return existsSync(join(this.indexDir, MANIFEST_FILE));\n }\n}\n\n/**\n * Create an indexer for a project\n */\nexport function createIndexer(\n projectRoot: string,\n options?: IndexerOptions\n): IncrementalIndexer {\n return new IncrementalIndexer(projectRoot, options);\n}\n","/**\n * Vector Store\n *\n * File-based vector storage with cosine similarity search.\n * Uses binary Float32 format for efficient storage.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\n\nexport interface SimilarityResult {\n /** Chunk ID */\n id: string;\n /** Cosine similarity score (0-1) */\n score: number;\n /** Distance (1 - score) */\n distance: number;\n}\n\nexport interface VectorStoreOptions {\n /** Expected dimension of vectors (validated on add) */\n dimension?: number;\n}\n\n/**\n * Compute cosine similarity between two vectors\n */\nfunction cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n\n normA = Math.sqrt(normA);\n normB = Math.sqrt(normB);\n\n if (normA === 0 || normB === 0) {\n return 0;\n }\n\n return dotProduct / (normA * normB);\n}\n\nexport class VectorStore {\n private vectors: Map<string, number[]> = new Map();\n private dimension: number | null = null;\n private idIndex: string[] = []; // Ordered list of IDs for binary storage\n\n constructor(options: VectorStoreOptions = {}) {\n if (options.dimension) {\n this.dimension = options.dimension;\n }\n }\n\n /**\n * Add a vector to the store\n */\n add(id: string, vector: number[]): void {\n // Validate dimension\n if (this.dimension === null) {\n this.dimension = vector.length;\n } else if (vector.length !== this.dimension) {\n throw new Error(\n `Vector dimension mismatch: expected ${this.dimension}, got ${vector.length}`\n );\n }\n\n // Add to store\n if (!this.vectors.has(id)) {\n this.idIndex.push(id);\n }\n this.vectors.set(id, vector);\n }\n\n /**\n * Add multiple vectors at once\n */\n addBatch(items: Array<{ id: string; vector: number[] }>): void {\n for (const { id, vector } of items) {\n this.add(id, vector);\n }\n }\n\n /**\n * Remove a vector from the store\n */\n remove(id: string): boolean {\n if (!this.vectors.has(id)) {\n return false;\n }\n this.vectors.delete(id);\n this.idIndex = this.idIndex.filter((i) => i !== id);\n return true;\n }\n\n /**\n * Get a vector by ID\n */\n get(id: string): number[] | null {\n return this.vectors.get(id) || null;\n }\n\n /**\n * Check if a vector exists\n */\n has(id: string): boolean {\n return this.vectors.has(id);\n }\n\n /**\n * Find the most similar vectors to a query vector\n */\n findSimilar(\n query: number[],\n k: number = 10,\n threshold: number = 0\n ): SimilarityResult[] {\n if (this.dimension !== null && query.length !== this.dimension) {\n throw new Error(\n `Query vector dimension mismatch: expected ${this.dimension}, got ${query.length}`\n );\n }\n\n const results: SimilarityResult[] = [];\n\n for (const [id, vector] of this.vectors) {\n const score = cosineSimilarity(query, vector);\n if (score >= threshold) {\n results.push({\n id,\n score,\n distance: 1 - score,\n });\n }\n }\n\n // Sort by score descending\n results.sort((a, b) => b.score - a.score);\n\n // Return top k\n return results.slice(0, k);\n }\n\n /**\n * Get the number of vectors in the store\n */\n size(): number {\n return this.vectors.size;\n }\n\n /**\n * Get the dimension of vectors\n */\n getDimension(): number | null {\n return this.dimension;\n }\n\n /**\n * Get all IDs\n */\n getIds(): string[] {\n return [...this.idIndex];\n }\n\n /**\n * Clear all vectors\n */\n clear(): void {\n this.vectors.clear();\n this.idIndex = [];\n this.dimension = null;\n }\n\n /**\n * Save the vector store to disk\n *\n * Format:\n * - embeddings.bin: Binary Float32 vectors\n * - ids.json: Ordered array of IDs matching vector positions\n */\n async save(dirPath: string): Promise<void> {\n // Ensure directory exists\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n\n // Save IDs\n const idsPath = join(dirPath, \"ids.json\");\n writeFileSync(idsPath, JSON.stringify(this.idIndex), \"utf-8\");\n\n // Save vectors as binary\n const embeddingsPath = join(dirPath, \"embeddings.bin\");\n\n if (this.vectors.size === 0) {\n // Write empty file with header only\n const header = new Uint32Array([0, 0]); // dimension=0, count=0\n writeFileSync(embeddingsPath, Buffer.from(header.buffer));\n return;\n }\n\n const dimension = this.dimension!;\n const count = this.vectors.size;\n\n // Create buffer: 8 bytes header (2 uint32) + vectors\n const headerSize = 8;\n const vectorsSize = count * dimension * 4; // Float32 = 4 bytes\n const buffer = Buffer.alloc(headerSize + vectorsSize);\n\n // Write header\n buffer.writeUInt32LE(dimension, 0);\n buffer.writeUInt32LE(count, 4);\n\n // Write vectors in ID order\n let offset = headerSize;\n for (const id of this.idIndex) {\n const vector = this.vectors.get(id)!;\n for (const value of vector) {\n buffer.writeFloatLE(value, offset);\n offset += 4;\n }\n }\n\n writeFileSync(embeddingsPath, buffer);\n }\n\n /**\n * Load the vector store from disk\n */\n async load(dirPath: string): Promise<void> {\n const idsPath = join(dirPath, \"ids.json\");\n const embeddingsPath = join(dirPath, \"embeddings.bin\");\n\n if (!existsSync(idsPath) || !existsSync(embeddingsPath)) {\n throw new Error(`Vector store files not found in ${dirPath}`);\n }\n\n // Clear current state\n this.clear();\n\n // Load IDs\n const idsContent = readFileSync(idsPath, \"utf-8\");\n this.idIndex = JSON.parse(idsContent);\n\n // Load vectors\n const buffer = readFileSync(embeddingsPath);\n\n // Read header\n const dimension = buffer.readUInt32LE(0);\n const count = buffer.readUInt32LE(4);\n\n if (count === 0) {\n // Empty store\n return;\n }\n\n this.dimension = dimension;\n\n // Read vectors\n let offset = 8;\n for (let i = 0; i < count; i++) {\n const vector: number[] = [];\n for (let j = 0; j < dimension; j++) {\n vector.push(buffer.readFloatLE(offset));\n offset += 4;\n }\n this.vectors.set(this.idIndex[i], vector);\n }\n }\n\n /**\n * Iterate over all vectors\n */\n *entries(): IterableIterator<[string, number[]]> {\n for (const id of this.idIndex) {\n yield [id, this.vectors.get(id)!];\n }\n }\n\n /**\n * Get stats about the store\n */\n getStats(): { size: number; dimension: number | null; memoryBytes: number } {\n const memoryBytes = this.dimension\n ? this.vectors.size * this.dimension * 4 + this.idIndex.length * 50 // Rough estimate\n : 0;\n\n return {\n size: this.vectors.size,\n dimension: this.dimension,\n memoryBytes,\n };\n }\n}\n","/**\n * Metadata Store\n *\n * JSON-based storage for chunk metadata (file paths, line numbers, etc.)\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport type { StoredChunkMetadata } from \"./types.js\";\n\nexport class MetadataStore {\n private chunks: Map<string, StoredChunkMetadata> = new Map();\n\n /**\n * Add or update chunk metadata\n */\n set(id: string, metadata: StoredChunkMetadata): void {\n this.chunks.set(id, metadata);\n }\n\n /**\n * Add multiple chunks at once\n */\n setBatch(items: Array<{ id: string; metadata: StoredChunkMetadata }>): void {\n for (const { id, metadata } of items) {\n this.set(id, metadata);\n }\n }\n\n /**\n * Get chunk metadata by ID\n */\n get(id: string): StoredChunkMetadata | null {\n return this.chunks.get(id) || null;\n }\n\n /**\n * Check if a chunk exists\n */\n has(id: string): boolean {\n return this.chunks.has(id);\n }\n\n /**\n * Remove chunk metadata\n */\n remove(id: string): boolean {\n return this.chunks.delete(id);\n }\n\n /**\n * Remove all chunks for a given file path\n */\n removeByFilePath(filePath: string): string[] {\n const removedIds: string[] = [];\n for (const [id, metadata] of this.chunks) {\n if (metadata.filePath === filePath) {\n this.chunks.delete(id);\n removedIds.push(id);\n }\n }\n return removedIds;\n }\n\n /**\n * Get all chunks for a given file path\n */\n getByFilePath(\n filePath: string\n ): Array<{ id: string; metadata: StoredChunkMetadata }> {\n const results: Array<{ id: string; metadata: StoredChunkMetadata }> = [];\n for (const [id, metadata] of this.chunks) {\n if (metadata.filePath === filePath) {\n results.push({ id, metadata });\n }\n }\n return results;\n }\n\n /**\n * Get chunk by content hash\n */\n getByContentHash(\n contentHash: string\n ): { id: string; metadata: StoredChunkMetadata } | null {\n for (const [id, metadata] of this.chunks) {\n if (metadata.contentHash === contentHash) {\n return { id, metadata };\n }\n }\n return null;\n }\n\n /**\n * Get chunk at a specific location\n */\n getAtLocation(\n filePath: string,\n line: number\n ): { id: string; metadata: StoredChunkMetadata } | null {\n for (const [id, metadata] of this.chunks) {\n if (\n metadata.filePath === filePath &&\n metadata.startLine <= line &&\n metadata.endLine >= line\n ) {\n return { id, metadata };\n }\n }\n return null;\n }\n\n /**\n * Get all unique file paths\n */\n getFilePaths(): string[] {\n const paths = new Set<string>();\n for (const metadata of this.chunks.values()) {\n paths.add(metadata.filePath);\n }\n return [...paths];\n }\n\n /**\n * Get number of chunks\n */\n size(): number {\n return this.chunks.size;\n }\n\n /**\n * Clear all metadata\n */\n clear(): void {\n this.chunks.clear();\n }\n\n /**\n * Iterate over all chunks\n */\n *entries(): IterableIterator<[string, StoredChunkMetadata]> {\n yield* this.chunks.entries();\n }\n\n /**\n * Get all IDs\n */\n getIds(): string[] {\n return [...this.chunks.keys()];\n }\n\n /**\n * Save to disk\n */\n async save(dirPath: string): Promise<void> {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n\n const metadataPath = join(dirPath, \"metadata.json\");\n const data = Object.fromEntries(this.chunks);\n writeFileSync(metadataPath, JSON.stringify(data, null, 2), \"utf-8\");\n }\n\n /**\n * Load from disk\n */\n async load(dirPath: string): Promise<void> {\n const metadataPath = join(dirPath, \"metadata.json\");\n\n if (!existsSync(metadataPath)) {\n throw new Error(`Metadata file not found: ${metadataPath}`);\n }\n\n this.clear();\n const content = readFileSync(metadataPath, \"utf-8\");\n const data = JSON.parse(content) as Record<string, StoredChunkMetadata>;\n\n for (const [id, metadata] of Object.entries(data)) {\n this.chunks.set(id, metadata);\n }\n }\n\n /**\n * Filter chunks by kind\n */\n filterByKind(\n kind: string\n ): Array<{ id: string; metadata: StoredChunkMetadata }> {\n const results: Array<{ id: string; metadata: StoredChunkMetadata }> = [];\n for (const [id, metadata] of this.chunks) {\n if (metadata.kind === kind) {\n results.push({ id, metadata });\n }\n }\n return results;\n }\n\n /**\n * Search by name (case-insensitive partial match)\n */\n searchByName(\n query: string\n ): Array<{ id: string; metadata: StoredChunkMetadata }> {\n const lowerQuery = query.toLowerCase();\n const results: Array<{ id: string; metadata: StoredChunkMetadata }> = [];\n for (const [id, metadata] of this.chunks) {\n if (metadata.name && metadata.name.toLowerCase().includes(lowerQuery)) {\n results.push({ id, metadata });\n }\n }\n return results;\n }\n}\n","/**\n * File Tracker\n *\n * Tracks file content hashes for incremental updates.\n * Uses xxhash for fast hashing (following uilint-eslint patterns).\n */\n\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n statSync,\n} from \"fs\";\nimport { join } from \"path\";\n\n// Lazy-loaded xxhash\nlet xxhashInstance: Awaited<\n ReturnType<typeof import(\"xxhash-wasm\")[\"default\"]>\n> | null = null;\n\nasync function getXxhash() {\n if (!xxhashInstance) {\n const xxhash = await import(\"xxhash-wasm\");\n xxhashInstance = await xxhash.default();\n }\n return xxhashInstance;\n}\n\n/**\n * Synchronous hash using djb2 algorithm (fallback)\n */\nfunction djb2Hash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString(16);\n}\n\n/**\n * Hash content using xxhash (async) or djb2 (sync fallback)\n */\nexport async function hashContent(content: string): Promise<string> {\n try {\n const xxhash = await getXxhash();\n return xxhash.h64ToString(content);\n } catch {\n return djb2Hash(content);\n }\n}\n\n/**\n * Synchronous hash for when async is not possible\n */\nexport function hashContentSync(content: string): string {\n return djb2Hash(content);\n}\n\nexport interface FileHashEntry {\n /** xxhash of file content */\n contentHash: string;\n /** Last modification time in ms */\n mtimeMs: number;\n /** IDs of chunks from this file */\n chunkIds: string[];\n}\n\nexport interface HashStore {\n version: number;\n files: Record<string, FileHashEntry>;\n}\n\nexport interface FileChange {\n path: string;\n type: \"added\" | \"modified\" | \"deleted\";\n oldHash?: string;\n newHash?: string;\n}\n\nconst HASH_STORE_VERSION = 1;\n\nexport class FileTracker {\n private store: HashStore = {\n version: HASH_STORE_VERSION,\n files: {},\n };\n\n /**\n * Get the hash entry for a file\n */\n getEntry(filePath: string): FileHashEntry | null {\n return this.store.files[filePath] || null;\n }\n\n /**\n * Set the hash entry for a file\n */\n setEntry(filePath: string, entry: FileHashEntry): void {\n this.store.files[filePath] = entry;\n }\n\n /**\n * Remove the hash entry for a file\n */\n removeEntry(filePath: string): boolean {\n if (this.store.files[filePath]) {\n delete this.store.files[filePath];\n return true;\n }\n return false;\n }\n\n /**\n * Get all tracked file paths\n */\n getTrackedFiles(): string[] {\n return Object.keys(this.store.files);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.store = {\n version: HASH_STORE_VERSION,\n files: {},\n };\n }\n\n /**\n * Detect changes between current files and stored hashes\n */\n async detectChanges(files: string[]): Promise<FileChange[]> {\n const changes: FileChange[] = [];\n const currentFiles = new Set(files);\n\n // Check for deleted files\n for (const storedPath of Object.keys(this.store.files)) {\n if (!currentFiles.has(storedPath)) {\n changes.push({\n path: storedPath,\n type: \"deleted\",\n oldHash: this.store.files[storedPath].contentHash,\n });\n }\n }\n\n // Check for added or modified files\n for (const filePath of files) {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const newHash = await hashContent(content);\n const stat = statSync(filePath);\n\n const entry = this.store.files[filePath];\n\n if (!entry) {\n // New file\n changes.push({\n path: filePath,\n type: \"added\",\n newHash,\n });\n } else if (entry.contentHash !== newHash) {\n // Modified file\n changes.push({\n path: filePath,\n type: \"modified\",\n oldHash: entry.contentHash,\n newHash,\n });\n }\n // If hash matches and mtime is similar, no change\n } catch (error) {\n // File might be deleted or unreadable\n if (this.store.files[filePath]) {\n changes.push({\n path: filePath,\n type: \"deleted\",\n oldHash: this.store.files[filePath].contentHash,\n });\n }\n }\n }\n\n return changes;\n }\n\n /**\n * Update stored hash for a file\n */\n async updateFile(\n filePath: string,\n content: string,\n chunkIds: string[]\n ): Promise<void> {\n const hash = await hashContent(content);\n const stat = statSync(filePath);\n\n this.store.files[filePath] = {\n contentHash: hash,\n mtimeMs: stat.mtimeMs,\n chunkIds,\n };\n }\n\n /**\n * Save to disk\n */\n async save(dirPath: string): Promise<void> {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n\n const hashesPath = join(dirPath, \"hashes.json\");\n writeFileSync(hashesPath, JSON.stringify(this.store, null, 2), \"utf-8\");\n }\n\n /**\n * Load from disk\n */\n async load(dirPath: string): Promise<void> {\n const hashesPath = join(dirPath, \"hashes.json\");\n\n if (!existsSync(hashesPath)) {\n // No existing hash store - start fresh\n this.clear();\n return;\n }\n\n const content = readFileSync(hashesPath, \"utf-8\");\n const data = JSON.parse(content) as HashStore;\n\n // Version check\n if (data.version !== HASH_STORE_VERSION) {\n // Incompatible version - start fresh\n this.clear();\n return;\n }\n\n this.store = data;\n }\n\n /**\n * Get stats\n */\n getStats(): { trackedFiles: number } {\n return {\n trackedFiles: Object.keys(this.store.files).length,\n };\n }\n}\n","/**\n * Duplicate Scorer\n *\n * Provides scoring functions for ranking duplicate code groups.\n */\n\nimport type { StoredChunkMetadata } from \"../index/types.js\";\n\nexport interface DuplicateScore {\n /** Embedding cosine similarity (0-1) */\n similarity: number;\n /** Ratio of code size similarity (0-1) */\n sizeRatio: number;\n /** Weighted combined score */\n combinedScore: number;\n}\n\n/**\n * Calculate the size ratio between two code chunks.\n * Returns a value between 0 and 1 where 1 means identical size.\n */\nexport function calculateSizeRatio(\n chunk1: StoredChunkMetadata,\n chunk2: StoredChunkMetadata\n): number {\n const lines1 = chunk1.endLine - chunk1.startLine + 1;\n const lines2 = chunk2.endLine - chunk2.startLine + 1;\n\n const minLines = Math.min(lines1, lines2);\n const maxLines = Math.max(lines1, lines2);\n\n return maxLines > 0 ? minLines / maxLines : 1;\n}\n\n/**\n * Calculate a combined duplicate score.\n */\nexport function calculateDuplicateScore(\n similarity: number,\n chunk1: StoredChunkMetadata,\n chunk2: StoredChunkMetadata\n): DuplicateScore {\n const sizeRatio = calculateSizeRatio(chunk1, chunk2);\n\n // Weighted score: 85% similarity, 15% size ratio\n const combinedScore = similarity * 0.85 + sizeRatio * 0.15;\n\n return {\n similarity,\n sizeRatio,\n combinedScore,\n };\n}\n\n/**\n * Calculate the average similarity of a duplicate group.\n */\nexport function calculateGroupAverageSimilarity(\n similarities: number[]\n): number {\n if (similarities.length === 0) return 0;\n return similarities.reduce((sum, s) => sum + s, 0) / similarities.length;\n}\n\n/**\n * Sort duplicate groups by relevance.\n * Groups are sorted by: member count (desc), then average similarity (desc).\n */\nexport function sortDuplicateGroups<T extends { avgSimilarity: number; members: unknown[] }>(\n groups: T[]\n): T[] {\n return [...groups].sort((a, b) => {\n // First by member count (more members = more important)\n const countDiff = b.members.length - a.members.length;\n if (countDiff !== 0) return countDiff;\n\n // Then by average similarity\n return b.avgSimilarity - a.avgSimilarity;\n });\n}\n","/**\n * Duplicate Finder\n *\n * Finds groups of semantically similar code chunks using the vector index.\n */\n\nimport type { VectorStore, SimilarityResult } from \"../index/vector-store.js\";\nimport type { MetadataStore } from \"../index/metadata-store.js\";\nimport type { StoredChunkMetadata } from \"../index/types.js\";\nimport type { ChunkKind } from \"../embeddings/types.js\";\nimport {\n calculateGroupAverageSimilarity,\n sortDuplicateGroups,\n} from \"./scorer.js\";\n\nexport interface DuplicateMember {\n /** Chunk ID */\n id: string;\n /** Chunk metadata */\n metadata: StoredChunkMetadata;\n /** Similarity score to the group centroid/first member */\n score: number;\n}\n\nexport interface DuplicateGroup {\n /** Members of the duplicate group */\n members: DuplicateMember[];\n /** Average similarity between all group members */\n avgSimilarity: number;\n /** The kind of code in this group (component, hook, function) */\n kind: ChunkKind;\n}\n\nexport interface FindDuplicatesOptions {\n /** Minimum cosine similarity threshold (0-1). Default: 0.85 */\n threshold?: number;\n /** Minimum group size. Default: 2 */\n minGroupSize?: number;\n /** Filter by chunk kind */\n kind?: ChunkKind;\n /** Exclude specific file paths */\n excludePaths?: string[];\n}\n\n/**\n * Find groups of semantically similar code.\n *\n * Algorithm:\n * 1. Iterate through all chunks\n * 2. For each unprocessed chunk, find similar chunks above threshold\n * 3. Group similar chunks together\n * 4. Mark all grouped chunks as processed\n * 5. Sort groups by size and similarity\n */\nexport function findDuplicateGroups(\n vectorStore: VectorStore,\n metadataStore: MetadataStore,\n options: FindDuplicatesOptions = {}\n): DuplicateGroup[] {\n const {\n threshold = 0.85,\n minGroupSize = 2,\n kind,\n excludePaths = [],\n } = options;\n\n const groups: DuplicateGroup[] = [];\n const processed = new Set<string>();\n\n // Get all entries and filter by kind if specified\n let entries = [...metadataStore.entries()];\n\n if (kind) {\n entries = entries.filter(([, meta]) => meta.kind === kind);\n }\n\n // Exclude specified paths\n if (excludePaths.length > 0) {\n entries = entries.filter(\n ([, meta]) => !excludePaths.some((p) => meta.filePath.includes(p))\n );\n }\n\n for (const [id, metadata] of entries) {\n if (processed.has(id)) continue;\n\n const vector = vectorStore.get(id);\n if (!vector) continue;\n\n // Find similar chunks\n const similar = vectorStore.findSimilar(vector, 50, threshold);\n\n // Filter out self, already-processed, and potentially filter by kind\n let candidates = similar.filter((s) => {\n if (s.id === id) return false;\n if (processed.has(s.id)) return false;\n\n const candidateMeta = metadataStore.get(s.id);\n if (!candidateMeta) return false;\n\n // If kind filter is set, only include same kind\n if (kind && candidateMeta.kind !== kind) return false;\n\n // Exclude paths\n if (excludePaths.some((p) => candidateMeta.filePath.includes(p)))\n return false;\n\n return true;\n });\n\n // If not filtering by kind, prefer same-kind groupings\n if (!kind && candidates.length > 0) {\n const sameKindCandidates = candidates.filter((c) => {\n const meta = metadataStore.get(c.id);\n return meta?.kind === metadata.kind;\n });\n if (sameKindCandidates.length > 0) {\n candidates = sameKindCandidates;\n }\n }\n\n // Check if we have enough candidates for a group\n if (candidates.length >= minGroupSize - 1) {\n const members: DuplicateMember[] = [\n { id, metadata, score: 1.0 }, // First member (reference)\n ];\n\n const similarities: number[] = [];\n\n for (const candidate of candidates) {\n const candidateMeta = metadataStore.get(candidate.id);\n if (candidateMeta) {\n members.push({\n id: candidate.id,\n metadata: candidateMeta,\n score: candidate.score,\n });\n similarities.push(candidate.score);\n processed.add(candidate.id);\n }\n }\n\n // Mark the original chunk as processed\n processed.add(id);\n\n groups.push({\n members,\n avgSimilarity: calculateGroupAverageSimilarity(similarities),\n kind: metadata.kind,\n });\n }\n }\n\n // Sort groups by relevance\n return sortDuplicateGroups(groups);\n}\n\n/**\n * Find similar code to a given location (file:line).\n */\nexport function findSimilarToLocation(\n vectorStore: VectorStore,\n metadataStore: MetadataStore,\n filePath: string,\n line: number,\n options: { top?: number; threshold?: number } = {}\n): SimilarityResult[] {\n const { top = 10, threshold = 0.5 } = options;\n\n // Find the chunk at this location\n const chunk = metadataStore.getAtLocation(filePath, line);\n if (!chunk) {\n return [];\n }\n\n // Get the vector for this chunk\n const vector = vectorStore.get(chunk.id);\n if (!vector) {\n return [];\n }\n\n // Find similar chunks (excluding self)\n const similar = vectorStore.findSimilar(vector, top + 1, threshold);\n\n return similar.filter((s) => s.id !== chunk.id).slice(0, top);\n}\n\n/**\n * Search for code similar to a text query.\n * Requires embedding the query first.\n */\nexport function findSimilarToQuery(\n vectorStore: VectorStore,\n queryEmbedding: number[],\n options: { top?: number; threshold?: number } = {}\n): SimilarityResult[] {\n const { top = 10, threshold = 0.5 } = options;\n\n return vectorStore.findSimilar(queryEmbedding, top, threshold);\n}\n"],"mappings":"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","names":["existsSync","mkdirSync","readFileSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","mkdirSync","writeFileSync"]}
|