bluera-knowledge 0.9.37 → 0.9.39
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/.env.example +12 -0
- package/CHANGELOG.md +47 -0
- package/README.md +27 -1
- package/dist/{chunk-CGDEV2RC.js → chunk-HUEWT6U5.js} +92 -16
- package/dist/chunk-HUEWT6U5.js.map +1 -0
- package/dist/{chunk-AT6G626F.js → chunk-IZWOEBFM.js} +2 -2
- package/dist/{chunk-6TKD5XE4.js → chunk-TIGPI3BE.js} +15 -6
- package/dist/chunk-TIGPI3BE.js.map +1 -0
- package/dist/index.js +23 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +3 -2
- package/dist/workers/background-worker-cli.js.map +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/src/cli/commands/crawl.test.ts +1 -0
- package/src/cli/commands/crawl.ts +2 -0
- package/src/cli/commands/index-cmd.test.ts +1 -0
- package/src/cli/commands/search.ts +22 -4
- package/src/db/lance.ts +2 -2
- package/src/mcp/handlers/search.handler.ts +7 -2
- package/src/mcp/schemas/index.ts +5 -0
- package/src/mcp/server.ts +5 -0
- package/src/services/index.service.test.ts +1 -0
- package/src/services/index.service.ts +2 -0
- package/src/services/search.service.test.ts +191 -3
- package/src/services/search.service.ts +121 -18
- package/src/types/search.ts +8 -0
- package/src/workers/background-worker.test.ts +1 -0
- package/src/workers/background-worker.ts +2 -0
- package/dist/chunk-6TKD5XE4.js.map +0 -1
- package/dist/chunk-CGDEV2RC.js.map +0 -1
- /package/dist/{chunk-AT6G626F.js.map → chunk-IZWOEBFM.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logging/logger.ts","../src/logging/payload.ts","../src/services/job.service.ts","../src/types/result.ts","../src/services/code-graph.service.ts","../src/analysis/ast-parser.ts","../src/analysis/code-graph.ts","../src/analysis/tree-sitter-parser.ts","../src/analysis/go-ast-parser.ts","../src/analysis/parser-factory.ts","../src/analysis/python-ast-parser.ts","../src/analysis/rust-ast-parser.ts","../src/services/config.service.ts","../src/services/project-root.service.ts","../src/types/config.ts","../src/services/index.service.ts","../src/services/chunking.service.ts","../src/types/brands.ts","../src/services/code-unit.service.ts","../src/services/search.service.ts","../src/services/store.service.ts","../src/plugin/git-clone.ts","../src/crawl/bridge.ts","../src/crawl/schemas.ts","../src/db/embeddings.ts","../src/db/lance.ts","../src/services/index.ts"],"sourcesContent":["/**\n * Core logger factory using pino with file-based rolling logs\n *\n * Features:\n * - File-only output (no console pollution for Claude Code)\n * - Size-based rotation (10MB, keeps 5 files)\n * - LOG_LEVEL env var control (trace/debug/info/warn/error/fatal)\n * - Child loggers per module for context\n */\n\nimport { mkdirSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport pino, { type Logger, type LoggerOptions } from 'pino';\n\n/** Valid log levels */\nexport type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nconst VALID_LEVELS: readonly LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\nconst VALID_LEVELS_SET: ReadonlySet<string> = new Set(VALID_LEVELS);\n\n/** Default log directory under user home */\nfunction getLogDir(): string {\n return join(homedir(), '.bluera', 'bluera-knowledge', 'logs');\n}\n\n/** Resolve and create log directory - fails fast if cannot create */\nfunction ensureLogDir(): string {\n const logDir = getLogDir();\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n return logDir;\n}\n\n/** Check if a string is a valid log level */\nfunction isValidLogLevel(level: string): level is LogLevel {\n return VALID_LEVELS_SET.has(level);\n}\n\n/** Get log level from environment - fails fast on invalid value */\nfunction getLogLevel(): LogLevel {\n const level = process.env['LOG_LEVEL']?.toLowerCase();\n\n if (level === undefined || level === '') {\n return 'info';\n }\n\n if (!isValidLogLevel(level)) {\n throw new Error(`Invalid LOG_LEVEL: \"${level}\". Valid values: ${VALID_LEVELS.join(', ')}`);\n }\n\n return level;\n}\n\n/** Root logger instance - lazily initialized */\nlet rootLogger: Logger | null = null;\n\n/** Initialize the root logger with pino-roll transport */\nfunction initializeLogger(): Logger {\n if (rootLogger !== null) {\n return rootLogger;\n }\n\n const logDir = ensureLogDir();\n const logFile = join(logDir, 'app.log');\n const level = getLogLevel();\n\n const options: LoggerOptions = {\n level,\n timestamp: pino.stdTimeFunctions.isoTime,\n formatters: {\n level: (label) => ({ level: label }),\n },\n transport: {\n target: 'pino-roll',\n options: {\n file: logFile,\n size: '10m', // 10MB rotation\n limit: { count: 5 }, // Keep 5 rotated files\n mkdir: true,\n },\n },\n };\n\n rootLogger = pino(options);\n return rootLogger;\n}\n\n/**\n * Create a named child logger for a specific module\n *\n * @param module - Module name (e.g., 'crawler', 'mcp-server', 'search-service')\n * @returns Logger instance with module context\n *\n * @example\n * const logger = createLogger('crawler');\n * logger.info({ url }, 'Fetching page');\n */\nexport function createLogger(module: string): Logger {\n const root = initializeLogger();\n return root.child({ module });\n}\n\n/**\n * Get the current log level\n */\nexport function getCurrentLogLevel(): LogLevel {\n return getLogLevel();\n}\n\n/**\n * Check if a specific log level is enabled\n */\nexport function isLevelEnabled(level: LogLevel): boolean {\n const currentLevel = getLogLevel();\n const currentIndex = VALID_LEVELS.indexOf(currentLevel);\n const checkIndex = VALID_LEVELS.indexOf(level);\n return checkIndex >= currentIndex;\n}\n\n/**\n * Get the log directory path\n */\nexport function getLogDirectory(): string {\n return getLogDir();\n}\n\n/**\n * Flush and shutdown the logger - call before process exit\n */\nexport function shutdownLogger(): Promise<void> {\n return new Promise((resolve) => {\n if (rootLogger !== null) {\n rootLogger.flush();\n // Give time for async transport to flush\n setTimeout(() => {\n rootLogger = null;\n resolve();\n }, 100);\n } else {\n resolve();\n }\n });\n}\n","/**\n * Large payload handling utilities for logging\n *\n * Handles large content (raw HTML, MCP responses) by:\n * - Truncating to preview in log entries\n * - Optionally dumping full content to separate files at trace level\n */\n\nimport { createHash } from 'node:crypto';\nimport { writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getLogDirectory, isLevelEnabled } from './logger.js';\n\n/** Maximum characters for log preview */\nconst MAX_PREVIEW_LENGTH = 500;\n\n/** Minimum size to trigger payload dump (10KB) */\nconst PAYLOAD_DUMP_THRESHOLD = 10_000;\n\n/** Summary of a large payload for logging */\nexport interface PayloadSummary {\n /** Truncated preview of content */\n preview: string;\n /** Size in bytes */\n sizeBytes: number;\n /** Short hash for identification */\n hash: string;\n /** Filename if full content was dumped (trace level only) */\n payloadFile?: string;\n}\n\n/** Get the payload dump directory */\nfunction getPayloadDir(): string {\n const dir = join(getLogDirectory(), 'payload');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\n/** Generate a safe filename from an identifier */\nfunction safeFilename(identifier: string): string {\n return identifier.replace(/[^a-zA-Z0-9-]/g, '_').substring(0, 50);\n}\n\n/**\n * Summarize a large payload for logging\n *\n * Creates a summary with:\n * - Truncated preview (first 500 chars)\n * - Size in bytes\n * - Short MD5 hash for identification\n * - Optional full dump to file at trace level\n *\n * @param content - The full content to summarize\n * @param type - Type identifier (e.g., 'raw-html', 'mcp-response')\n * @param identifier - Unique identifier (e.g., URL, query)\n * @param dumpFull - Whether to dump full content to file (default: trace level check)\n * @returns PayloadSummary for inclusion in log entry\n *\n * @example\n * logger.info({\n * url,\n * ...summarizePayload(html, 'raw-html', url),\n * }, 'Fetched HTML');\n */\nexport function summarizePayload(\n content: string,\n type: string,\n identifier: string,\n dumpFull: boolean = isLevelEnabled('trace')\n): PayloadSummary {\n const sizeBytes = Buffer.byteLength(content, 'utf8');\n const hash = createHash('md5').update(content).digest('hex').substring(0, 12);\n const preview = truncateForLog(content, MAX_PREVIEW_LENGTH);\n\n const baseSummary = { preview, sizeBytes, hash };\n\n // Dump full payload to file if enabled and above threshold\n if (dumpFull && sizeBytes > PAYLOAD_DUMP_THRESHOLD) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const safeId = safeFilename(identifier);\n const filename = `${timestamp}-${type}-${safeId}-${hash}.json`;\n const filepath = join(getPayloadDir(), filename);\n\n writeFileSync(\n filepath,\n JSON.stringify(\n {\n timestamp: new Date().toISOString(),\n type,\n identifier,\n sizeBytes,\n content,\n },\n null,\n 2\n )\n );\n\n return { ...baseSummary, payloadFile: filename };\n }\n\n return baseSummary;\n}\n\n/**\n * Truncate content for logging with ellipsis indicator\n *\n * @param content - Content to truncate\n * @param maxLength - Maximum length (default: 500)\n * @returns Truncated string with '... [truncated]' if needed\n */\nexport function truncateForLog(content: string, maxLength: number = MAX_PREVIEW_LENGTH): string {\n if (content.length <= maxLength) {\n return content;\n }\n return `${content.substring(0, maxLength)}... [truncated]`;\n}\n","import { randomUUID } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { Result, ok, err } from '../types/result.js';\nimport type { Job, CreateJobParams, UpdateJobParams, JobStatus } from '../types/job.js';\n\nexport class JobService {\n private readonly jobsDir: string;\n\n constructor(dataDir?: string) {\n // Default to ~/.local/share/bluera-knowledge/jobs\n const baseDir =\n dataDir ??\n path.join(\n process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.',\n '.local/share/bluera-knowledge'\n );\n this.jobsDir = path.join(baseDir, 'jobs');\n\n // Ensure jobs directory exists\n if (!fs.existsSync(this.jobsDir)) {\n fs.mkdirSync(this.jobsDir, { recursive: true });\n }\n }\n\n /**\n * Create a new job\n */\n createJob(params: CreateJobParams): Job {\n const job: Job = {\n id: `job_${randomUUID().replace(/-/g, '').substring(0, 12)}`,\n type: params.type,\n status: 'pending',\n progress: 0,\n message: params.message ?? `${params.type} job created`,\n details: params.details,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n // Write job to file\n this.writeJob(job);\n\n return job;\n }\n\n /**\n * Update an existing job\n */\n updateJob(jobId: string, updates: UpdateJobParams): void {\n const job = this.getJob(jobId);\n\n if (!job) {\n throw new Error(`Job ${jobId} not found`);\n }\n\n // Merge updates\n if (updates.status !== undefined) {\n job.status = updates.status;\n }\n if (updates.progress !== undefined) {\n job.progress = updates.progress;\n }\n if (updates.message !== undefined) {\n job.message = updates.message;\n }\n if (updates.details !== undefined) {\n job.details = { ...job.details, ...updates.details };\n }\n\n job.updatedAt = new Date().toISOString();\n\n // Write updated job\n this.writeJob(job);\n }\n\n /**\n * Get a job by ID\n */\n getJob(jobId: string): Job | null {\n const jobFile = path.join(this.jobsDir, `${jobId}.json`);\n\n if (!fs.existsSync(jobFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(jobFile, 'utf-8');\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return JSON.parse(content) as Job;\n } catch (error) {\n console.error(`Error reading job ${jobId}:`, error);\n return null;\n }\n }\n\n /**\n * List all jobs with optional status filter\n */\n listJobs(statusFilter?: JobStatus | JobStatus[]): Job[] {\n if (!fs.existsSync(this.jobsDir)) {\n return [];\n }\n\n const files = fs.readdirSync(this.jobsDir);\n const jobs: Job[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.json') || file.endsWith('.pid')) {\n continue;\n }\n\n try {\n const content = fs.readFileSync(path.join(this.jobsDir, file), 'utf-8');\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const job = JSON.parse(content) as Job;\n\n if (statusFilter !== undefined) {\n const filters = Array.isArray(statusFilter) ? statusFilter : [statusFilter];\n if (filters.includes(job.status)) {\n jobs.push(job);\n }\n } else {\n jobs.push(job);\n }\n } catch (error) {\n console.error(`Error reading job file ${file}:`, error);\n }\n }\n\n // Sort by updated time (most recent first)\n jobs.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n\n return jobs;\n }\n\n /**\n * List active jobs (pending or running)\n */\n listActiveJobs(): Job[] {\n return this.listJobs(['pending', 'running']);\n }\n\n /**\n * Cancel a job\n */\n cancelJob(jobId: string): Result<void> {\n const job = this.getJob(jobId);\n\n if (!job) {\n return err(new Error(`Job ${jobId} not found`));\n }\n\n if (job.status === 'completed' || job.status === 'failed') {\n return err(new Error(`Cannot cancel ${job.status} job`));\n }\n\n if (job.status === 'cancelled') {\n return ok(undefined);\n }\n\n // Update job status\n this.updateJob(jobId, {\n status: 'cancelled',\n message: 'Job cancelled by user',\n details: { cancelledAt: new Date().toISOString() },\n });\n\n // Kill worker process if it exists\n const pidFile = path.join(this.jobsDir, `${jobId}.pid`);\n if (fs.existsSync(pidFile)) {\n try {\n const pid = parseInt(fs.readFileSync(pidFile, 'utf-8'), 10);\n // Validate PID: must be positive integer > 0\n // PID 0 = sends to process group (DANGEROUS - kills terminal!)\n // Negative PIDs have special meanings in kill()\n if (!Number.isNaN(pid) && Number.isInteger(pid) && pid > 0) {\n process.kill(pid, 'SIGTERM');\n }\n } catch {\n // Process may have already exited, ignore\n }\n // Always delete the PID file, even if kill failed\n try {\n fs.unlinkSync(pidFile);\n } catch {\n // Ignore if file already deleted\n }\n }\n\n return ok(undefined);\n }\n\n /**\n * Clean up old completed/failed/cancelled jobs\n */\n cleanupOldJobs(olderThanHours: number = 24): number {\n const jobs = this.listJobs();\n const cutoffTime = Date.now() - olderThanHours * 60 * 60 * 1000;\n let cleaned = 0;\n\n for (const job of jobs) {\n if (\n (job.status === 'completed' || job.status === 'failed' || job.status === 'cancelled') &&\n new Date(job.updatedAt).getTime() < cutoffTime\n ) {\n const jobFile = path.join(this.jobsDir, `${job.id}.json`);\n try {\n fs.unlinkSync(jobFile);\n cleaned++;\n } catch (error) {\n console.error(`Error deleting job file ${job.id}:`, error);\n }\n }\n }\n\n return cleaned;\n }\n\n /**\n * Delete a specific job\n */\n deleteJob(jobId: string): boolean {\n const jobFile = path.join(this.jobsDir, `${jobId}.json`);\n\n if (!fs.existsSync(jobFile)) {\n return false;\n }\n\n try {\n fs.unlinkSync(jobFile);\n return true;\n } catch (error) {\n console.error(`Error deleting job ${jobId}:`, error);\n return false;\n }\n }\n\n /**\n * Write job to file\n */\n private writeJob(job: Job): void {\n const jobFile = path.join(this.jobsDir, `${job.id}.json`);\n fs.writeFileSync(jobFile, JSON.stringify(job, null, 2), 'utf-8');\n }\n}\n","export type Result<T, E = Error> =\n | { readonly success: true; readonly data: T }\n | { readonly success: false; readonly error: E };\n\nexport function ok<T>(data: T): Result<T, never> {\n return { success: true, data };\n}\n\nexport function err<E>(error: E): Result<never, E> {\n return { success: false, error };\n}\n\nexport function isOk<T, E>(result: Result<T, E>): result is { success: true; data: T } {\n return result.success;\n}\n\nexport function isErr<T, E>(result: Result<T, E>): result is { success: false; error: E } {\n return !result.success;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (isOk(result)) {\n return result.data;\n }\n // Type guard ensures result has 'error' property\n if (isErr(result)) {\n if (result.error instanceof Error) {\n throw result.error;\n }\n throw new Error(String(result.error));\n }\n // This should never happen due to discriminated union\n throw new Error('Invalid result type');\n}\n\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n if (isOk(result)) {\n return result.data;\n }\n return defaultValue;\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { ASTParser } from '../analysis/ast-parser.js';\nimport { CodeGraph, type GraphNode } from '../analysis/code-graph.js';\nimport { GoASTParser } from '../analysis/go-ast-parser.js';\nimport { ParserFactory } from '../analysis/parser-factory.js';\nimport { RustASTParser } from '../analysis/rust-ast-parser.js';\nimport type { PythonBridge } from '../crawl/bridge.js';\nimport type { StoreId } from '../types/brands.js';\n\ninterface SerializedGraph {\n nodes: Array<{\n id: string;\n file: string;\n type: string;\n name: string;\n exported: boolean;\n startLine: number;\n endLine: number;\n signature?: string;\n }>;\n edges: Array<{\n from: string;\n to: string;\n type: string;\n confidence: number;\n }>;\n}\n\n/**\n * Service for building, persisting, and querying code graphs.\n * Code graphs track relationships between code elements (functions, classes, etc.)\n * for enhanced search context.\n */\nexport class CodeGraphService {\n private readonly dataDir: string;\n private readonly parser: ASTParser;\n private readonly parserFactory: ParserFactory;\n private readonly graphCache: Map<string, CodeGraph>;\n\n constructor(dataDir: string, pythonBridge?: PythonBridge) {\n this.dataDir = dataDir;\n this.parser = new ASTParser();\n this.parserFactory = new ParserFactory(pythonBridge);\n this.graphCache = new Map();\n }\n\n /**\n * Build a code graph from source files.\n */\n async buildGraph(files: Array<{ path: string; content: string }>): Promise<CodeGraph> {\n const graph = new CodeGraph();\n\n for (const file of files) {\n const ext = file.path.split('.').pop() ?? '';\n if (!['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go'].includes(ext)) continue;\n\n // Parse nodes (functions, classes, etc.) using the factory\n const nodes = await this.parserFactory.parseFile(file.path, file.content);\n graph.addNodes(nodes, file.path);\n\n // Parse imports and add edges\n if (ext === 'rs') {\n // Use RustASTParser for Rust imports\n const rustParser = new RustASTParser();\n const imports = rustParser.extractImports(file.content);\n for (const imp of imports) {\n if (!imp.isType) {\n graph.addImport(file.path, imp.source, imp.specifiers);\n }\n }\n } else if (ext === 'go') {\n // Use GoASTParser for Go imports\n const goParser = new GoASTParser();\n const imports = goParser.extractImports(file.content);\n for (const imp of imports) {\n if (!imp.isType) {\n graph.addImport(file.path, imp.source, imp.specifiers);\n }\n }\n } else if (ext !== 'py') {\n // Use ASTParser for JS/TS imports (Python imports handled by Python parser)\n const imports = this.parser.extractImports(file.content);\n for (const imp of imports) {\n if (!imp.isType) {\n graph.addImport(file.path, imp.source, imp.specifiers);\n }\n }\n }\n\n // Analyze call relationships for each function/method\n for (const node of nodes) {\n const lines = file.content.split('\\n');\n\n if (node.type === 'function') {\n // Extract the function body for call analysis\n const functionCode = lines.slice(node.startLine - 1, node.endLine).join('\\n');\n graph.analyzeCallRelationships(functionCode, file.path, node.name);\n } else if (node.type === 'class' && node.methods !== undefined) {\n // For classes, analyze each method separately\n for (const method of node.methods) {\n const methodCode = lines.slice(method.startLine - 1, method.endLine).join('\\n');\n graph.analyzeCallRelationships(methodCode, file.path, `${node.name}.${method.name}`);\n }\n }\n }\n }\n\n return graph;\n }\n\n /**\n * Save a code graph for a store.\n */\n async saveGraph(storeId: StoreId, graph: CodeGraph): Promise<void> {\n const graphPath = this.getGraphPath(storeId);\n await mkdir(dirname(graphPath), { recursive: true });\n\n const serialized = graph.toJSON();\n await writeFile(graphPath, JSON.stringify(serialized, null, 2));\n }\n\n /**\n * Load a code graph for a store.\n * Returns undefined if no graph exists.\n */\n async loadGraph(storeId: StoreId): Promise<CodeGraph | undefined> {\n // Check cache first\n const cached = this.graphCache.get(storeId);\n if (cached) return cached;\n\n const graphPath = this.getGraphPath(storeId);\n\n try {\n const content = await readFile(graphPath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n\n // Validate structure\n if (!this.isSerializedGraph(parsed)) {\n return undefined;\n }\n\n const serialized = parsed;\n const graph = new CodeGraph();\n\n // Restore nodes\n for (const node of serialized.nodes) {\n const nodeType = this.validateNodeType(node.type);\n if (!nodeType) continue;\n\n // Method nodes are added directly to the graph since they're already separate nodes\n if (nodeType === 'method') {\n const graphNode: GraphNode = {\n id: node.id,\n file: node.file,\n type: 'method',\n name: node.name,\n exported: node.exported,\n startLine: node.startLine,\n endLine: node.endLine,\n };\n if (node.signature !== undefined) {\n graphNode.signature = node.signature;\n }\n graph.addGraphNode(graphNode);\n continue;\n }\n\n const codeNode: {\n type: 'function' | 'class' | 'interface' | 'type' | 'const';\n name: string;\n exported: boolean;\n startLine: number;\n endLine: number;\n signature?: string;\n } = {\n type: nodeType,\n name: node.name,\n exported: node.exported,\n startLine: node.startLine,\n endLine: node.endLine,\n };\n if (node.signature !== undefined) {\n codeNode.signature = node.signature;\n }\n graph.addNodes([codeNode], node.file);\n }\n\n // Restore edges\n for (const edge of serialized.edges) {\n const edgeType = this.validateEdgeType(edge.type);\n if (!edgeType) continue;\n\n graph.addEdge({\n from: edge.from,\n to: edge.to,\n type: edgeType,\n confidence: edge.confidence,\n });\n }\n\n this.graphCache.set(storeId, graph);\n return graph;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get usage stats for a code element.\n */\n getUsageStats(\n graph: CodeGraph,\n filePath: string,\n symbolName: string\n ): { calledBy: number; calls: number } {\n const nodeId = `${filePath}:${symbolName}`;\n return {\n calledBy: graph.getCalledByCount(nodeId),\n calls: graph.getCallsCount(nodeId),\n };\n }\n\n /**\n * Get related code (callers and callees) for a code element.\n */\n getRelatedCode(\n graph: CodeGraph,\n filePath: string,\n symbolName: string\n ): Array<{ id: string; relationship: string }> {\n const nodeId = `${filePath}:${symbolName}`;\n const related: Array<{ id: string; relationship: string }> = [];\n\n // Get callers (incoming call edges)\n const incoming = graph.getIncomingEdges(nodeId);\n for (const edge of incoming) {\n if (edge.type === 'calls') {\n related.push({ id: edge.from, relationship: 'calls this' });\n }\n }\n\n // Get callees (outgoing call edges)\n const outgoing = graph.getEdges(nodeId);\n for (const edge of outgoing) {\n if (edge.type === 'calls') {\n related.push({ id: edge.to, relationship: 'called by this' });\n }\n }\n\n return related;\n }\n\n /**\n * Clear cached graphs.\n */\n clearCache(): void {\n this.graphCache.clear();\n }\n\n private getGraphPath(storeId: StoreId): string {\n return join(this.dataDir, 'graphs', `${storeId}.json`);\n }\n\n /**\n * Type guard for SerializedGraph structure.\n */\n private isSerializedGraph(value: unknown): value is SerializedGraph {\n if (typeof value !== 'object' || value === null) return false;\n // Use 'in' operator for property checking\n if (!('nodes' in value) || !('edges' in value)) return false;\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- narrowed via 'in' checks above\n const obj = value as { nodes: unknown; edges: unknown };\n return Array.isArray(obj.nodes) && Array.isArray(obj.edges);\n }\n\n /**\n * Type guard for valid node types.\n */\n private isValidNodeType(\n type: string\n ): type is 'function' | 'class' | 'interface' | 'type' | 'const' | 'method' {\n return ['function', 'class', 'interface', 'type', 'const', 'method'].includes(type);\n }\n\n /**\n * Validate and return a node type, or undefined if invalid.\n */\n private validateNodeType(\n type: string\n ): 'function' | 'class' | 'interface' | 'type' | 'const' | 'method' | undefined {\n if (this.isValidNodeType(type)) {\n return type;\n }\n return undefined;\n }\n\n /**\n * Type guard for valid edge types.\n */\n private isValidEdgeType(type: string): type is 'calls' | 'imports' | 'extends' | 'implements' {\n return ['calls', 'imports', 'extends', 'implements'].includes(type);\n }\n\n /**\n * Validate and return an edge type, or undefined if invalid.\n */\n private validateEdgeType(\n type: string\n ): 'calls' | 'imports' | 'extends' | 'implements' | undefined {\n if (this.isValidEdgeType(type)) {\n return type;\n }\n return undefined;\n }\n}\n","import { parse, type ParserPlugin } from '@babel/parser';\nimport traverseModule from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { NodePath } from '@babel/traverse';\n\n// Handle both ESM and CJS module formats\ntype TraverseFunction = (ast: t.File, visitor: Record<string, unknown>) => void;\nfunction getTraverse(mod: unknown): TraverseFunction {\n if (typeof mod === 'function') {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return mod as TraverseFunction;\n }\n if (mod !== null && typeof mod === 'object' && 'default' in mod) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const withDefault = mod as { default: unknown };\n if (typeof withDefault.default === 'function') {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return withDefault.default as TraverseFunction;\n }\n }\n throw new Error('Invalid traverse module export');\n}\nconst traverse = getTraverse(traverseModule);\n\nexport interface CodeNode {\n type: 'function' | 'class' | 'interface' | 'type' | 'const';\n name: string;\n exported: boolean;\n async?: boolean;\n startLine: number;\n endLine: number;\n signature?: string;\n methods?: Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }>;\n}\n\nexport interface ImportInfo {\n source: string;\n specifiers: string[];\n isType: boolean;\n}\n\nexport class ASTParser {\n parse(code: string, language: 'typescript' | 'javascript'): CodeNode[] {\n try {\n const plugins: ParserPlugin[] = ['jsx'];\n if (language === 'typescript') {\n plugins.push('typescript');\n }\n\n const ast = parse(code, {\n sourceType: 'module',\n plugins,\n });\n\n const nodes: CodeNode[] = [];\n\n traverse(ast, {\n FunctionDeclaration: (path: NodePath<t.FunctionDeclaration>) => {\n const node = path.node;\n if (!node.id) return;\n\n const exported =\n path.parent.type === 'ExportNamedDeclaration' ||\n path.parent.type === 'ExportDefaultDeclaration';\n\n nodes.push({\n type: 'function',\n name: node.id.name,\n exported,\n async: node.async,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n signature: this.extractFunctionSignature(node),\n });\n },\n\n ClassDeclaration: (path: NodePath<t.ClassDeclaration>) => {\n const node = path.node;\n if (!node.id) return;\n\n const exported =\n path.parent.type === 'ExportNamedDeclaration' ||\n path.parent.type === 'ExportDefaultDeclaration';\n\n const methods: CodeNode['methods'] = [];\n\n for (const member of node.body.body) {\n if (t.isClassMethod(member) && t.isIdentifier(member.key)) {\n methods.push({\n name: member.key.name,\n async: member.async,\n signature: this.extractMethodSignature(member),\n startLine: member.loc?.start.line ?? 0,\n endLine: member.loc?.end.line ?? 0,\n });\n }\n }\n\n nodes.push({\n type: 'class',\n name: node.id.name,\n exported,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n methods,\n });\n },\n\n TSInterfaceDeclaration: (path: NodePath<t.TSInterfaceDeclaration>) => {\n const node = path.node;\n\n const exported = path.parent.type === 'ExportNamedDeclaration';\n\n nodes.push({\n type: 'interface',\n name: node.id.name,\n exported,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n });\n },\n });\n\n return nodes;\n } catch {\n // Return empty array for malformed code\n return [];\n }\n }\n\n extractImports(code: string): ImportInfo[] {\n try {\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n });\n\n const imports: ImportInfo[] = [];\n\n traverse(ast, {\n ImportDeclaration: (path: NodePath<t.ImportDeclaration>) => {\n const node = path.node;\n const specifiers: string[] = [];\n\n for (const spec of node.specifiers) {\n if (t.isImportDefaultSpecifier(spec)) {\n specifiers.push(spec.local.name);\n } else if (t.isImportSpecifier(spec)) {\n specifiers.push(spec.local.name);\n } else if (t.isImportNamespaceSpecifier(spec)) {\n specifiers.push(spec.local.name);\n }\n }\n\n imports.push({\n source: node.source.value,\n specifiers,\n isType: node.importKind === 'type',\n });\n },\n });\n\n return imports;\n } catch {\n // Return empty array for malformed code\n return [];\n }\n }\n\n private extractFunctionSignature(node: t.FunctionDeclaration): string {\n const params = node.params\n .map((p) => {\n if (t.isIdentifier(p)) return p.name;\n return 'param';\n })\n .join(', ');\n\n return `${node.id?.name ?? 'anonymous'}(${params})`;\n }\n\n private extractMethodSignature(node: t.ClassMethod): string {\n const params = node.params\n .map((p) => {\n if (t.isIdentifier(p)) return p.name;\n return 'param';\n })\n .join(', ');\n\n const name = t.isIdentifier(node.key) ? node.key.name : 'method';\n return `${name}(${params})`;\n }\n}\n","import type { CodeNode } from './ast-parser.js';\n\nexport interface GraphNode {\n id: string;\n file: string;\n type: 'function' | 'class' | 'interface' | 'type' | 'const' | 'method';\n name: string;\n exported: boolean;\n startLine: number;\n endLine: number;\n signature?: string;\n}\n\nexport interface GraphEdge {\n from: string;\n to: string;\n type: 'calls' | 'imports' | 'extends' | 'implements';\n confidence: number;\n}\n\nexport class CodeGraph {\n private readonly nodes: Map<string, GraphNode> = new Map<string, GraphNode>();\n private readonly edges: Map<string, GraphEdge[]> = new Map<string, GraphEdge[]>();\n\n addNodes(nodes: CodeNode[], file: string): void {\n for (const node of nodes) {\n const id = `${file}:${node.name}`;\n\n const graphNode: GraphNode = {\n id,\n file,\n type: node.type,\n name: node.name,\n exported: node.exported,\n startLine: node.startLine,\n endLine: node.endLine,\n };\n\n if (node.signature !== undefined) {\n graphNode.signature = node.signature;\n }\n\n this.nodes.set(id, graphNode);\n\n // Initialize edges array for this node\n if (!this.edges.has(id)) {\n this.edges.set(id, []);\n }\n\n // If this is a class with methods, create separate nodes for each method\n if (node.type === 'class' && node.methods !== undefined) {\n for (const method of node.methods) {\n const methodId = `${file}:${node.name}.${method.name}`;\n\n const methodNode: GraphNode = {\n id: methodId,\n file,\n type: 'method',\n name: method.name,\n exported: node.exported, // Methods inherit export status from class\n startLine: method.startLine,\n endLine: method.endLine,\n signature: method.signature,\n };\n\n this.nodes.set(methodId, methodNode);\n\n // Initialize edges array for this method\n if (!this.edges.has(methodId)) {\n this.edges.set(methodId, []);\n }\n }\n }\n }\n }\n\n addImport(fromFile: string, toFile: string, specifiers: string[]): void {\n // Normalize the toFile path (resolve relative imports)\n const resolvedTo = this.resolveImportPath(fromFile, toFile);\n\n for (const spec of specifiers) {\n const edge: GraphEdge = {\n from: fromFile,\n to: `${resolvedTo}:${spec}`,\n type: 'imports',\n confidence: 1.0,\n };\n\n const edges = this.edges.get(fromFile) ?? [];\n edges.push(edge);\n this.edges.set(fromFile, edges);\n }\n }\n\n analyzeCallRelationships(code: string, file: string, functionName: string): void {\n const nodeId = `${file}:${functionName}`;\n\n // Simple regex-based call detection (can be enhanced with AST later)\n const callPattern = /\\b([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\(/g;\n const calls = new Set<string>();\n\n let match;\n while ((match = callPattern.exec(code)) !== null) {\n if (match[1] !== undefined && match[1] !== '') {\n calls.add(match[1]);\n }\n }\n\n const edges = this.edges.get(nodeId) ?? [];\n\n for (const calledFunction of calls) {\n // Try to find the called function in the graph\n const targetNode = this.findNodeByName(calledFunction);\n\n if (targetNode) {\n edges.push({\n from: nodeId,\n to: targetNode.id,\n type: 'calls',\n confidence: 0.8, // Lower confidence for regex-based detection\n });\n } else {\n // Unknown function, possibly from import\n edges.push({\n from: nodeId,\n to: `unknown:${calledFunction}`,\n type: 'calls',\n confidence: 0.5,\n });\n }\n }\n\n this.edges.set(nodeId, edges);\n }\n\n getNode(id: string): GraphNode | undefined {\n return this.nodes.get(id);\n }\n\n getEdges(nodeId: string): GraphEdge[] {\n return this.edges.get(nodeId) ?? [];\n }\n\n /**\n * Add an edge to the graph (used when restoring from serialized data)\n */\n addEdge(edge: GraphEdge): void {\n const edges = this.edges.get(edge.from) ?? [];\n edges.push(edge);\n this.edges.set(edge.from, edges);\n }\n\n /**\n * Add a graph node directly (used when restoring from serialized data)\n */\n addGraphNode(node: GraphNode): void {\n this.nodes.set(node.id, node);\n\n // Initialize edges array for this node if it doesn't exist\n if (!this.edges.has(node.id)) {\n this.edges.set(node.id, []);\n }\n }\n\n /**\n * Get edges where this node is the target (callers of this function)\n */\n getIncomingEdges(nodeId: string): GraphEdge[] {\n const incoming: GraphEdge[] = [];\n for (const edges of this.edges.values()) {\n for (const edge of edges) {\n if (edge.to === nodeId) {\n incoming.push(edge);\n }\n }\n }\n return incoming;\n }\n\n /**\n * Count how many nodes call this node\n */\n getCalledByCount(nodeId: string): number {\n return this.getIncomingEdges(nodeId).filter((e) => e.type === 'calls').length;\n }\n\n /**\n * Count how many nodes this node calls\n */\n getCallsCount(nodeId: string): number {\n return this.getEdges(nodeId).filter((e) => e.type === 'calls').length;\n }\n\n getAllNodes(): GraphNode[] {\n return Array.from(this.nodes.values());\n }\n\n private findNodeByName(name: string): GraphNode | undefined {\n for (const node of this.nodes.values()) {\n if (node.name === name) {\n return node;\n }\n }\n return undefined;\n }\n\n private resolveImportPath(fromFile: string, importPath: string): string {\n // Simple resolution - can be enhanced\n if (importPath.startsWith('.')) {\n // Relative import\n const fromDir = fromFile.split('/').slice(0, -1).join('/');\n const parts = importPath.split('/');\n\n let resolved = fromDir;\n for (const part of parts) {\n if (part === '..') {\n resolved = resolved.split('/').slice(0, -1).join('/');\n } else if (part !== '.') {\n resolved += `/${part}`;\n }\n }\n\n return resolved.replace(/\\.js$/, '');\n }\n\n // Package import\n return importPath;\n }\n\n toJSON(): { nodes: GraphNode[]; edges: Array<{ from: string; to: string; type: string }> } {\n const allEdges: GraphEdge[] = [];\n for (const edges of this.edges.values()) {\n allEdges.push(...edges);\n }\n\n return {\n nodes: Array.from(this.nodes.values()),\n edges: allEdges.map((e) => ({ from: e.from, to: e.to, type: e.type })),\n };\n }\n}\n","import Parser from 'tree-sitter';\nimport Go from 'tree-sitter-go';\nimport Rust from 'tree-sitter-rust';\n\n/**\n * Tree-sitter infrastructure for parsing Rust and Go code.\n * Provides utilities for AST traversal, querying, and position conversion.\n */\n\nexport interface TreeSitterPosition {\n row: number;\n column: number;\n}\n\nexport interface TreeSitterNode {\n type: string;\n text: string;\n startPosition: TreeSitterPosition;\n endPosition: TreeSitterPosition;\n startIndex: number;\n endIndex: number;\n childCount: number;\n namedChildCount: number;\n children: TreeSitterNode[];\n namedChildren: TreeSitterNode[];\n parent: TreeSitterNode | null;\n nextSibling: TreeSitterNode | null;\n previousSibling: TreeSitterNode | null;\n firstChild: TreeSitterNode | null;\n lastChild: TreeSitterNode | null;\n firstNamedChild: TreeSitterNode | null;\n lastNamedChild: TreeSitterNode | null;\n child(index: number): TreeSitterNode | null;\n namedChild(index: number): TreeSitterNode | null;\n childForFieldName(fieldName: string): TreeSitterNode | null;\n descendantsOfType(type: string | string[]): TreeSitterNode[];\n}\n\nexport interface TreeSitterTree {\n rootNode: TreeSitterNode;\n edit(delta: unknown): void;\n walk(): unknown;\n}\n\n/**\n * Initialize a tree-sitter parser for Rust\n */\nexport function createRustParser(): Parser {\n const parser = new Parser();\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- tree-sitter-rust lacks TypeScript definitions\n parser.setLanguage(Rust as Parser.Language);\n return parser;\n}\n\n/**\n * Parse Rust source code into an AST\n */\nexport function parseRustCode(code: string): TreeSitterTree | null {\n try {\n const parser = createRustParser();\n return parser.parse(code);\n } catch {\n // Return null for malformed code\n return null;\n }\n}\n\n/**\n * Initialize a tree-sitter parser for Go\n */\nexport function createGoParser(): Parser {\n const parser = new Parser();\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- tree-sitter-go lacks TypeScript definitions\n parser.setLanguage(Go as Parser.Language);\n return parser;\n}\n\n/**\n * Parse Go source code into an AST\n */\nexport function parseGoCode(code: string): TreeSitterTree | null {\n try {\n const parser = createGoParser();\n return parser.parse(code);\n } catch {\n // Return null for malformed code\n return null;\n }\n}\n\n/**\n * Convert tree-sitter position (0-indexed) to line number (1-indexed)\n */\nexport function positionToLineNumber(position: TreeSitterPosition): number {\n return position.row + 1;\n}\n\n/**\n * Get the text content of a node\n */\nexport function getNodeText(node: TreeSitterNode): string {\n return node.text;\n}\n\n/**\n * Get all children of a specific type\n */\nexport function getChildrenOfType(node: TreeSitterNode, type: string): TreeSitterNode[] {\n return node.children.filter((child) => child.type === type);\n}\n\n/**\n * Get the first child of a specific type\n */\nexport function getFirstChildOfType(node: TreeSitterNode, type: string): TreeSitterNode | null {\n return node.children.find((child) => child.type === type) ?? null;\n}\n\n/**\n * Get child by field name (e.g., \"name\", \"body\", \"parameters\")\n */\nexport function getChildByFieldName(\n node: TreeSitterNode,\n fieldName: string\n): TreeSitterNode | null {\n return node.childForFieldName(fieldName);\n}\n\n/**\n * Check if node has a visibility modifier (pub)\n */\nexport function hasVisibilityModifier(node: TreeSitterNode): boolean {\n return node.children.some((child) => child.type === 'visibility_modifier');\n}\n\n/**\n * Get visibility modifier text (e.g., \"pub\", \"pub(crate)\")\n */\nexport function getVisibilityModifier(node: TreeSitterNode): string | null {\n const visNode = node.children.find((child) => child.type === 'visibility_modifier');\n return visNode !== undefined ? visNode.text : null;\n}\n\n/**\n * Check if a function is async\n */\nexport function isAsyncFunction(node: TreeSitterNode): boolean {\n // Check for 'async' keyword in function_item or function_signature_item\n return node.children.some((child) => child.type === 'async' || child.text === 'async');\n}\n\n/**\n * Check if a function is unsafe\n */\nexport function isUnsafeFunction(node: TreeSitterNode): boolean {\n return node.children.some((child) => child.type === 'unsafe' || child.text === 'unsafe');\n}\n\n/**\n * Extract function signature including generics and parameters\n */\nexport function getFunctionSignature(node: TreeSitterNode): string {\n // Extract the full signature by getting text from name to return type\n const nameNode = getChildByFieldName(node, 'name');\n const parametersNode = getChildByFieldName(node, 'parameters');\n const returnTypeNode = getChildByFieldName(node, 'return_type');\n const typeParametersNode = getChildByFieldName(node, 'type_parameters');\n\n if (nameNode === null) {\n return '';\n }\n\n let signature = nameNode.text;\n\n // Add type parameters (generics)\n if (typeParametersNode !== null) {\n signature += typeParametersNode.text;\n }\n\n // Add parameters\n if (parametersNode !== null) {\n signature += parametersNode.text;\n }\n\n // Add return type\n if (returnTypeNode !== null) {\n signature += ` ${returnTypeNode.text}`;\n }\n\n return signature;\n}\n\n/**\n * Query nodes of specific type from the tree\n * @param tree The tree-sitter tree\n * @param nodeType The type of nodes to find (e.g., 'function_item', 'struct_item')\n * @returns Array of matching nodes\n */\nexport function queryNodesByType(\n tree: TreeSitterTree,\n nodeType: string | string[]\n): TreeSitterNode[] {\n const types = Array.isArray(nodeType) ? nodeType : [nodeType];\n return tree.rootNode.descendantsOfType(types);\n}\n\n/**\n * Extract use statement import path\n */\nexport function extractImportPath(useNode: TreeSitterNode): string {\n // Get the use_declaration argument\n const argumentNode = getChildByFieldName(useNode, 'argument');\n if (argumentNode === null) {\n return '';\n }\n return argumentNode.text;\n}\n","import {\n parseGoCode,\n queryNodesByType,\n positionToLineNumber,\n getChildByFieldName,\n getFunctionSignature,\n getFirstChildOfType,\n type TreeSitterNode,\n type TreeSitterTree,\n} from './tree-sitter-parser.js';\nimport type { CodeNode, ImportInfo } from './ast-parser.js';\n\n/**\n * Parser for Go code using tree-sitter\n * Extracts functions, methods, structs, interfaces, types, constants, and imports\n */\nexport class GoASTParser {\n /**\n * Parse Go code into CodeNode array\n * @param code Go source code\n * @param filePath File path for error context\n * @returns Array of CodeNode objects representing Go constructs\n */\n parse(code: string, _filePath: string): CodeNode[] {\n try {\n const tree = parseGoCode(code);\n if (tree === null) {\n // Malformed code - return empty array\n return [];\n }\n\n const nodes: CodeNode[] = [];\n\n // Parse functions\n const functions = this.parseFunctions(tree);\n nodes.push(...functions);\n\n // Parse structs\n const structs = this.parseStructs(tree);\n nodes.push(...structs);\n\n // Parse interfaces\n const interfaces = this.parseInterfaces(tree);\n nodes.push(...interfaces);\n\n // Parse type aliases\n const types = this.parseTypeAliases(tree);\n nodes.push(...types);\n\n // Parse constants and variables\n const constants = this.parseConstants(tree);\n nodes.push(...constants);\n\n // Parse methods and attach to structs\n this.parseMethods(tree, nodes);\n\n return nodes;\n } catch {\n // Return empty array for any parsing errors\n return [];\n }\n }\n\n /**\n * Extract imports from Go code\n * @param code Go source code\n * @returns Array of ImportInfo objects\n */\n extractImports(code: string): ImportInfo[] {\n try {\n const tree = parseGoCode(code);\n if (tree === null) {\n return [];\n }\n\n const imports: ImportInfo[] = [];\n const importDecls = queryNodesByType(tree, 'import_declaration');\n\n for (const importDecl of importDecls) {\n const importSpecs = importDecl.descendantsOfType('import_spec');\n\n for (const spec of importSpecs) {\n const pathNode = getChildByFieldName(spec, 'path');\n if (pathNode === null) {\n continue;\n }\n\n // Extract string content from interpreted_string_literal\n const stringContent = pathNode.descendantsOfType('interpreted_string_literal_content')[0];\n const path =\n stringContent !== undefined ? stringContent.text : pathNode.text.replace(/\"/g, '');\n\n if (path !== '') {\n imports.push({\n source: path,\n specifiers: [],\n isType: false,\n });\n }\n }\n }\n\n return imports;\n } catch {\n return [];\n }\n }\n\n /**\n * Parse function declarations\n */\n private parseFunctions(tree: TreeSitterTree): CodeNode[] {\n const functionNodes = queryNodesByType(tree, 'function_declaration');\n const nodes: CodeNode[] = [];\n\n for (const fnNode of functionNodes) {\n const nameNode = getChildByFieldName(fnNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(fnNode.startPosition);\n const endLine = positionToLineNumber(fnNode.endPosition);\n const signature = getFunctionSignature(fnNode);\n\n nodes.push({\n type: 'function',\n name,\n exported,\n async: false,\n startLine,\n endLine,\n signature,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse struct definitions\n */\n private parseStructs(tree: TreeSitterTree): CodeNode[] {\n const typeDecls = queryNodesByType(tree, 'type_declaration');\n const nodes: CodeNode[] = [];\n\n for (const typeDecl of typeDecls) {\n // Get type_spec child node\n const typeSpec = getFirstChildOfType(typeDecl, 'type_spec');\n if (typeSpec === null) {\n continue;\n }\n\n const nameNode = getChildByFieldName(typeSpec, 'name');\n const typeNode = getChildByFieldName(typeSpec, 'type');\n\n if (nameNode === null || typeNode === null) {\n continue;\n }\n\n // Check if it's a struct type\n if (typeNode.type !== 'struct_type') {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(typeDecl.startPosition);\n const endLine = positionToLineNumber(typeDecl.endPosition);\n\n nodes.push({\n type: 'class',\n name,\n exported,\n startLine,\n endLine,\n signature: name,\n methods: [],\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse interface definitions\n */\n private parseInterfaces(tree: TreeSitterTree): CodeNode[] {\n const typeDecls = queryNodesByType(tree, 'type_declaration');\n const nodes: CodeNode[] = [];\n\n for (const typeDecl of typeDecls) {\n const typeSpec = getFirstChildOfType(typeDecl, 'type_spec');\n if (typeSpec === null) {\n continue;\n }\n\n const nameNode = getChildByFieldName(typeSpec, 'name');\n const typeNode = getChildByFieldName(typeSpec, 'type');\n\n if (nameNode === null || typeNode === null) {\n continue;\n }\n\n // Check if it's an interface type\n if (typeNode.type !== 'interface_type') {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(typeDecl.startPosition);\n const endLine = positionToLineNumber(typeDecl.endPosition);\n\n // Extract interface methods\n const methods = this.extractInterfaceMethods(typeNode);\n\n nodes.push({\n type: 'interface',\n name,\n exported,\n startLine,\n endLine,\n signature: name,\n methods,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse type aliases\n */\n private parseTypeAliases(tree: TreeSitterTree): CodeNode[] {\n const typeDecls = queryNodesByType(tree, 'type_declaration');\n const nodes: CodeNode[] = [];\n\n for (const typeDecl of typeDecls) {\n const typeSpec = getFirstChildOfType(typeDecl, 'type_spec');\n if (typeSpec === null) {\n continue;\n }\n\n const nameNode = getChildByFieldName(typeSpec, 'name');\n const typeNode = getChildByFieldName(typeSpec, 'type');\n\n if (nameNode === null || typeNode === null) {\n continue;\n }\n\n // Skip struct and interface types (handled by other methods)\n if (typeNode.type === 'struct_type' || typeNode.type === 'interface_type') {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(typeDecl.startPosition);\n const endLine = positionToLineNumber(typeDecl.endPosition);\n const signature = `${name} = ${typeNode.text}`;\n\n nodes.push({\n type: 'type',\n name,\n exported,\n startLine,\n endLine,\n signature,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse constants and variables\n */\n private parseConstants(tree: TreeSitterTree): CodeNode[] {\n const nodes: CodeNode[] = [];\n\n // Parse const declarations\n const constDecls = queryNodesByType(tree, 'const_declaration');\n for (const constDecl of constDecls) {\n const specs = constDecl.descendantsOfType('const_spec');\n for (const spec of specs) {\n const nameNode = getChildByFieldName(spec, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(spec.startPosition);\n const endLine = positionToLineNumber(spec.endPosition);\n\n const typeNode = getChildByFieldName(spec, 'type');\n const signature = typeNode !== null ? `${name}: ${typeNode.text}` : name;\n\n nodes.push({\n type: 'const',\n name,\n exported,\n startLine,\n endLine,\n signature,\n });\n }\n }\n\n // Parse var declarations\n const varDecls = queryNodesByType(tree, 'var_declaration');\n for (const varDecl of varDecls) {\n const specs = varDecl.descendantsOfType('var_spec');\n for (const spec of specs) {\n const nameNode = getChildByFieldName(spec, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = this.isExported(name);\n const startLine = positionToLineNumber(spec.startPosition);\n const endLine = positionToLineNumber(spec.endPosition);\n\n const typeNode = getChildByFieldName(spec, 'type');\n const signature = typeNode !== null ? `${name}: ${typeNode.text}` : name;\n\n nodes.push({\n type: 'const',\n name,\n exported,\n startLine,\n endLine,\n signature,\n });\n }\n }\n\n return nodes;\n }\n\n /**\n * Parse methods and attach to corresponding structs\n */\n private parseMethods(tree: TreeSitterTree, nodes: CodeNode[]): void {\n const methodNodes = queryNodesByType(tree, 'method_declaration');\n\n for (const methodNode of methodNodes) {\n const receiverType = this.getReceiverType(methodNode);\n if (receiverType === null) {\n continue;\n }\n\n const nameNode = getChildByFieldName(methodNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const signature = getFunctionSignature(methodNode);\n const startLine = positionToLineNumber(methodNode.startPosition);\n const endLine = positionToLineNumber(methodNode.endPosition);\n\n // Find the corresponding struct and attach method\n const structNode = nodes.find((node) => node.type === 'class' && node.name === receiverType);\n\n if (structNode?.methods !== undefined) {\n structNode.methods.push({\n name,\n async: false,\n signature,\n startLine,\n endLine,\n });\n }\n }\n }\n\n /**\n * Extract methods from interface definition\n */\n private extractInterfaceMethods(interfaceNode: TreeSitterNode): Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> {\n const methods: Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> = [];\n\n const methodElems = interfaceNode.descendantsOfType('method_elem');\n\n for (const methodElem of methodElems) {\n const nameNode = getChildByFieldName(methodElem, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const signature = getFunctionSignature(methodElem);\n const startLine = positionToLineNumber(methodElem.startPosition);\n const endLine = positionToLineNumber(methodElem.endPosition);\n\n methods.push({\n name,\n async: false,\n signature,\n startLine,\n endLine,\n });\n }\n\n return methods;\n }\n\n /**\n * Get the receiver type name for a method\n */\n private getReceiverType(methodNode: TreeSitterNode): string | null {\n const receiverNode = getChildByFieldName(methodNode, 'receiver');\n if (receiverNode === null) {\n return null;\n }\n\n const paramDecl = getFirstChildOfType(receiverNode, 'parameter_declaration');\n if (paramDecl === null) {\n return null;\n }\n\n const typeNode = getChildByFieldName(paramDecl, 'type');\n if (typeNode === null) {\n return null;\n }\n\n // Handle pointer receivers (*Type)\n if (typeNode.type === 'pointer_type') {\n const innerType = typeNode.children.find((child) => child.type === 'type_identifier');\n return innerType !== undefined ? innerType.text : null;\n }\n\n // Handle value receivers (Type)\n if (typeNode.type === 'type_identifier') {\n return typeNode.text;\n }\n\n return null;\n }\n\n /**\n * Check if a name is exported (starts with uppercase letter)\n */\n private isExported(name: string): boolean {\n if (name.length === 0) {\n return false;\n }\n const firstChar = name[0];\n if (firstChar === undefined) {\n return false;\n }\n return firstChar === firstChar.toUpperCase();\n }\n}\n","import path from 'node:path';\nimport { ASTParser, type CodeNode } from './ast-parser.js';\nimport { GoASTParser } from './go-ast-parser.js';\nimport { PythonASTParser } from './python-ast-parser.js';\nimport { RustASTParser } from './rust-ast-parser.js';\nimport type { PythonBridge } from '../crawl/bridge.js';\n\nexport class ParserFactory {\n constructor(private readonly pythonBridge?: PythonBridge) {}\n\n async parseFile(filePath: string, code: string): Promise<CodeNode[]> {\n const ext = path.extname(filePath);\n\n if (['.ts', '.tsx'].includes(ext)) {\n const parser = new ASTParser();\n return parser.parse(code, 'typescript');\n }\n\n if (['.js', '.jsx'].includes(ext)) {\n const parser = new ASTParser();\n return parser.parse(code, 'javascript');\n }\n\n if (ext === '.py') {\n if (!this.pythonBridge) {\n throw new Error('Python bridge not available for parsing Python files');\n }\n const parser = new PythonASTParser(this.pythonBridge);\n return parser.parse(code, filePath);\n }\n\n if (ext === '.rs') {\n const parser = new RustASTParser();\n return parser.parse(code, filePath);\n }\n\n if (ext === '.go') {\n const parser = new GoASTParser();\n return parser.parse(code, filePath);\n }\n\n return [];\n }\n}\n","import type { CodeNode } from './ast-parser.js';\nimport type { PythonBridge, ParsePythonResult } from '../crawl/bridge.js';\n\nexport class PythonASTParser {\n constructor(private readonly bridge: PythonBridge) {}\n\n async parse(code: string, filePath: string): Promise<CodeNode[]> {\n const result: ParsePythonResult = await this.bridge.parsePython(code, filePath);\n\n return result.nodes.map((node) => {\n const codeNode: CodeNode = {\n type: node.type,\n name: node.name,\n exported: node.exported,\n startLine: node.startLine,\n endLine: node.endLine,\n };\n\n if (node.async !== undefined) {\n codeNode.async = node.async;\n }\n\n if (node.signature !== undefined) {\n codeNode.signature = node.signature;\n }\n\n if (node.methods !== undefined) {\n codeNode.methods = node.methods;\n }\n\n return codeNode;\n });\n }\n}\n","import {\n parseRustCode,\n queryNodesByType,\n positionToLineNumber,\n getChildByFieldName,\n hasVisibilityModifier,\n isAsyncFunction,\n getFunctionSignature,\n extractImportPath,\n type TreeSitterNode,\n type TreeSitterTree,\n} from './tree-sitter-parser.js';\nimport type { CodeNode, ImportInfo } from './ast-parser.js';\n\n/**\n * Parser for Rust code using tree-sitter\n * Extracts functions, structs, traits, types, constants, and imports\n */\nexport class RustASTParser {\n /**\n * Parse Rust code into CodeNode array\n * @param code Rust source code\n * @param filePath File path for error context\n * @returns Array of CodeNode objects representing Rust constructs\n */\n parse(code: string, _filePath: string): CodeNode[] {\n try {\n const tree = parseRustCode(code);\n if (tree === null) {\n // Malformed code - return empty array\n return [];\n }\n\n const nodes: CodeNode[] = [];\n\n // Parse functions\n const functions = this.parseFunctions(tree);\n nodes.push(...functions);\n\n // Parse structs\n const structs = this.parseStructs(tree);\n nodes.push(...structs);\n\n // Parse traits\n const traits = this.parseTraits(tree);\n nodes.push(...traits);\n\n // Parse type aliases\n const types = this.parseTypeAliases(tree);\n nodes.push(...types);\n\n // Parse constants and statics\n const constants = this.parseConstants(tree);\n nodes.push(...constants);\n\n // Parse impl blocks and attach methods to structs\n this.parseImplBlocks(tree, nodes);\n\n return nodes;\n } catch {\n // Return empty array for any parsing errors\n return [];\n }\n }\n\n /**\n * Extract imports from Rust code\n * @param code Rust source code\n * @returns Array of ImportInfo objects\n */\n extractImports(code: string): ImportInfo[] {\n try {\n const tree = parseRustCode(code);\n if (tree === null) {\n return [];\n }\n\n const useDeclarations = queryNodesByType(tree, 'use_declaration');\n const imports: ImportInfo[] = [];\n\n for (const useNode of useDeclarations) {\n const importPath = extractImportPath(useNode);\n if (importPath === '') {\n continue;\n }\n\n // Parse the import path to extract module and specifiers\n const { source, specifiers } = this.parseImportPath(importPath);\n\n imports.push({\n source,\n specifiers,\n isType: false, // Rust doesn't distinguish type-only imports at syntax level\n });\n }\n\n return imports;\n } catch {\n return [];\n }\n }\n\n /**\n * Parse function declarations (excluding impl block methods)\n */\n private parseFunctions(tree: TreeSitterTree): CodeNode[] {\n const functionNodes = queryNodesByType(tree, 'function_item');\n const nodes: CodeNode[] = [];\n\n for (const fnNode of functionNodes) {\n // Skip functions inside impl blocks - they'll be handled as methods\n if (this.isInsideImplBlock(fnNode)) {\n continue;\n }\n\n const nameNode = getChildByFieldName(fnNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = hasVisibilityModifier(fnNode);\n const async = isAsyncFunction(fnNode);\n const startLine = positionToLineNumber(fnNode.startPosition);\n const endLine = positionToLineNumber(fnNode.endPosition);\n const signature = getFunctionSignature(fnNode);\n\n nodes.push({\n type: 'function',\n name,\n exported,\n async,\n startLine,\n endLine,\n signature,\n });\n }\n\n return nodes;\n }\n\n /**\n * Check if a node is inside an impl block\n */\n private isInsideImplBlock(node: TreeSitterNode): boolean {\n let current = node.parent;\n while (current !== null) {\n if (current.type === 'impl_item') {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n\n /**\n * Parse struct definitions\n */\n private parseStructs(tree: TreeSitterTree): CodeNode[] {\n const structNodes = queryNodesByType(tree, 'struct_item');\n const nodes: CodeNode[] = [];\n\n for (const structNode of structNodes) {\n const nameNode = getChildByFieldName(structNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = hasVisibilityModifier(structNode);\n const startLine = positionToLineNumber(structNode.startPosition);\n const endLine = positionToLineNumber(structNode.endPosition);\n\n // Get type parameters (generics) if present\n const typeParamsNode = getChildByFieldName(structNode, 'type_parameters');\n const signature = typeParamsNode !== null ? `${name}${typeParamsNode.text}` : name;\n\n nodes.push({\n type: 'class',\n name,\n exported,\n startLine,\n endLine,\n signature,\n methods: [], // Will be populated by parseImplBlocks\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse trait definitions\n */\n private parseTraits(tree: TreeSitterTree): CodeNode[] {\n const traitNodes = queryNodesByType(tree, 'trait_item');\n const nodes: CodeNode[] = [];\n\n for (const traitNode of traitNodes) {\n const nameNode = getChildByFieldName(traitNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = hasVisibilityModifier(traitNode);\n const startLine = positionToLineNumber(traitNode.startPosition);\n const endLine = positionToLineNumber(traitNode.endPosition);\n\n // Get type parameters (generics) if present\n const typeParamsNode = getChildByFieldName(traitNode, 'type_parameters');\n const signature = typeParamsNode !== null ? `${name}${typeParamsNode.text}` : name;\n\n // Extract trait methods\n const methods = this.extractTraitMethods(traitNode);\n\n nodes.push({\n type: 'interface',\n name,\n exported,\n startLine,\n endLine,\n signature,\n methods,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse type aliases\n */\n private parseTypeAliases(tree: TreeSitterTree): CodeNode[] {\n const typeNodes = queryNodesByType(tree, 'type_item');\n const nodes: CodeNode[] = [];\n\n for (const typeNode of typeNodes) {\n const nameNode = getChildByFieldName(typeNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = hasVisibilityModifier(typeNode);\n const startLine = positionToLineNumber(typeNode.startPosition);\n const endLine = positionToLineNumber(typeNode.endPosition);\n\n // Get the full type alias definition\n const valueNode = getChildByFieldName(typeNode, 'type');\n const signature = valueNode !== null ? `${name} = ${valueNode.text}` : name;\n\n nodes.push({\n type: 'type',\n name,\n exported,\n startLine,\n endLine,\n signature,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse constants and statics\n */\n private parseConstants(tree: TreeSitterTree): CodeNode[] {\n const constNodes = queryNodesByType(tree, ['const_item', 'static_item']);\n const nodes: CodeNode[] = [];\n\n for (const constNode of constNodes) {\n const nameNode = getChildByFieldName(constNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const exported = hasVisibilityModifier(constNode);\n const startLine = positionToLineNumber(constNode.startPosition);\n const endLine = positionToLineNumber(constNode.endPosition);\n\n // Get type annotation\n const typeNode = getChildByFieldName(constNode, 'type');\n const signature = typeNode !== null ? `${name}: ${typeNode.text}` : name;\n\n nodes.push({\n type: 'const',\n name,\n exported,\n startLine,\n endLine,\n signature,\n });\n }\n\n return nodes;\n }\n\n /**\n * Parse impl blocks and attach methods to corresponding structs\n */\n private parseImplBlocks(tree: TreeSitterTree, nodes: CodeNode[]): void {\n const implNodes = queryNodesByType(tree, 'impl_item');\n\n for (const implNode of implNodes) {\n // Get the type being implemented\n const typeNode = getChildByFieldName(implNode, 'type');\n if (typeNode === null) {\n continue;\n }\n\n const typeName = typeNode.text;\n\n // Extract methods from impl block\n const methods = this.extractImplMethods(implNode);\n\n // Find the corresponding struct and attach methods\n const structNode = nodes.find((node) => node.type === 'class' && node.name === typeName);\n\n if (structNode?.methods !== undefined) {\n structNode.methods.push(...methods);\n }\n }\n }\n\n /**\n * Extract methods from trait definition\n */\n private extractTraitMethods(traitNode: TreeSitterNode): Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> {\n const methods: Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> = [];\n\n // Get declaration_list (trait body)\n const bodyNode = getChildByFieldName(traitNode, 'body');\n if (bodyNode === null) {\n return methods;\n }\n\n // Find all function_signature_item nodes (trait method declarations)\n const functionSignatures = bodyNode.descendantsOfType('function_signature_item');\n\n for (const fnSigNode of functionSignatures) {\n const nameNode = getChildByFieldName(fnSigNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const async = isAsyncFunction(fnSigNode);\n const signature = getFunctionSignature(fnSigNode);\n const startLine = positionToLineNumber(fnSigNode.startPosition);\n const endLine = positionToLineNumber(fnSigNode.endPosition);\n\n methods.push({\n name,\n async,\n signature,\n startLine,\n endLine,\n });\n }\n\n return methods;\n }\n\n /**\n * Extract methods from impl block\n */\n private extractImplMethods(implNode: TreeSitterNode): Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> {\n const methods: Array<{\n name: string;\n async: boolean;\n signature: string;\n startLine: number;\n endLine: number;\n }> = [];\n\n // Get declaration_list (impl body)\n const bodyNode = getChildByFieldName(implNode, 'body');\n if (bodyNode === null) {\n return methods;\n }\n\n // Find all function_item nodes (impl methods)\n const functionItems = bodyNode.descendantsOfType('function_item');\n\n for (const fnNode of functionItems) {\n const nameNode = getChildByFieldName(fnNode, 'name');\n if (nameNode === null) {\n continue;\n }\n\n const name = nameNode.text;\n const async = isAsyncFunction(fnNode);\n const signature = getFunctionSignature(fnNode);\n const startLine = positionToLineNumber(fnNode.startPosition);\n const endLine = positionToLineNumber(fnNode.endPosition);\n\n methods.push({\n name,\n async,\n signature,\n startLine,\n endLine,\n });\n }\n\n return methods;\n }\n\n /**\n * Parse import path into source and specifiers\n * Examples:\n * - \"std::collections::HashMap\" -> { source: \"std::collections\", specifiers: [\"HashMap\"] }\n * - \"crate::utils::*\" -> { source: \"crate::utils\", specifiers: [\"*\"] }\n * - \"super::Type\" -> { source: \"super\", specifiers: [\"Type\"] }\n */\n private parseImportPath(importPath: string): { source: string; specifiers: string[] } {\n // Remove whitespace\n const path = importPath.trim();\n\n // Handle glob imports (use std::io::*)\n if (path.includes('::*')) {\n const source = path.replace('::*', '');\n return { source, specifiers: ['*'] };\n }\n\n // Handle scoped imports: use std::io::{Read, Write}\n const scopedMatch = path.match(/^(.+)::\\{(.+)\\}$/);\n if (scopedMatch !== null) {\n const source = scopedMatch[1] ?? '';\n const specifiersStr = scopedMatch[2] ?? '';\n const specifiers = specifiersStr.split(',').map((s) => s.trim());\n return { source, specifiers };\n }\n\n // Handle simple imports: use std::collections::HashMap\n const parts = path.split('::');\n if (parts.length > 1) {\n const specifiers = [parts[parts.length - 1] ?? ''];\n const source = parts.slice(0, -1).join('::');\n return { source, specifiers };\n }\n\n // Single item import\n return { source: '', specifiers: [path] };\n }\n}\n","import { readFile, writeFile, mkdir, access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, resolve } from 'node:path';\nimport { ProjectRootService } from './project-root.service.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport type { AppConfig } from '../types/config.js';\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport class ConfigService {\n private readonly configPath: string;\n private readonly dataDir: string;\n private config: AppConfig | null = null;\n\n constructor(\n configPath = `${homedir()}/.bluera/bluera-knowledge/config.json`,\n dataDir?: string,\n projectRoot?: string\n ) {\n this.configPath = configPath;\n\n if (dataDir !== undefined && dataDir !== '') {\n // Explicit dataDir provided, use it as-is\n this.dataDir = dataDir;\n } else {\n // Resolve project root using hierarchical detection\n const root = projectRoot ?? ProjectRootService.resolve();\n // Expand relative default path against project root\n this.dataDir = this.expandPath(DEFAULT_CONFIG.dataDir, root);\n }\n }\n\n async load(): Promise<AppConfig> {\n if (this.config !== null) {\n return this.config;\n }\n\n const exists = await fileExists(this.configPath);\n if (!exists) {\n // First run - create config file with defaults\n this.config = { ...DEFAULT_CONFIG };\n await this.save(this.config);\n return this.config;\n }\n\n // File exists - load it (throws on corruption per CLAUDE.md \"fail early\")\n const content = await readFile(this.configPath, 'utf-8');\n try {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n this.config = { ...DEFAULT_CONFIG, ...JSON.parse(content) } as AppConfig;\n } catch (error) {\n throw new Error(\n `Failed to parse config file at ${this.configPath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n return this.config;\n }\n\n async save(config: AppConfig): Promise<void> {\n await mkdir(dirname(this.configPath), { recursive: true });\n await writeFile(this.configPath, JSON.stringify(config, null, 2));\n this.config = config;\n }\n\n resolveDataDir(): string {\n return this.dataDir;\n }\n\n private expandPath(path: string, baseDir: string): string {\n // Expand ~ to home directory\n if (path.startsWith('~')) {\n return path.replace('~', homedir());\n }\n // Resolve relative paths against base directory (not process.cwd())\n if (!path.startsWith('/')) {\n return resolve(baseDir, path);\n }\n // Return absolute paths as-is\n return path;\n }\n}\n","import { existsSync, statSync, realpathSync } from 'node:fs';\nimport { dirname, join, normalize, sep } from 'node:path';\n\nexport interface ProjectRootOptions {\n readonly projectRoot?: string | undefined;\n}\n\n/**\n * Service for resolving the project root directory using a hierarchical detection strategy.\n *\n * Resolution hierarchy:\n * 1. Explicit projectRoot option (highest priority)\n * 2. PROJECT_ROOT environment variable (set by plugin commands)\n * 3. PWD environment variable (set by MCP server and shells)\n * 4. Git root detection (walk up to find .git directory)\n * 5. process.cwd() (fallback)\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class ProjectRootService {\n /**\n * Resolve project root directory using hierarchical detection.\n */\n static resolve(options?: ProjectRootOptions): string {\n // 1. Check explicit option first\n if (options?.projectRoot !== undefined && options.projectRoot !== '') {\n return this.normalize(options.projectRoot);\n }\n\n // 2. Check PROJECT_ROOT environment variable (plugin commands)\n const projectRootEnv = process.env['PROJECT_ROOT'];\n if (projectRootEnv !== undefined && projectRootEnv !== '') {\n return this.normalize(projectRootEnv);\n }\n\n // 3. Check PWD environment variable (MCP server, shells)\n const pwdEnv = process.env['PWD'];\n if (pwdEnv !== undefined && pwdEnv !== '') {\n return this.normalize(pwdEnv);\n }\n\n // 4. Try git root detection\n const gitRoot = this.findGitRoot(process.cwd());\n if (gitRoot !== null) {\n return gitRoot;\n }\n\n // 5. Fallback to process.cwd()\n return process.cwd();\n }\n\n /**\n * Find git repository root by walking up the directory tree looking for .git\n */\n static findGitRoot(startPath: string): string | null {\n let currentPath = normalize(startPath);\n const root = normalize(sep); // Root filesystem (/ on Unix, C:\\ on Windows)\n\n // Walk up directory tree\n while (currentPath !== root) {\n const gitPath = join(currentPath, '.git');\n\n if (existsSync(gitPath)) {\n try {\n const stats = statSync(gitPath);\n // .git can be a directory (normal repo) or file (submodule/worktree)\n if (stats.isDirectory() || stats.isFile()) {\n return currentPath;\n }\n } catch {\n // Ignore stat errors, continue searching\n }\n }\n\n // Move up one directory\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n // Reached root without finding .git\n break;\n }\n currentPath = parentPath;\n }\n\n return null;\n }\n\n /**\n * Normalize path by resolving symlinks and normalizing separators\n */\n static normalize(path: string): string {\n try {\n // Resolve symlinks to real path\n const realPath = realpathSync(path);\n // Normalize separators\n return normalize(realPath);\n } catch {\n // If realpath fails (path doesn't exist), just normalize\n return normalize(path);\n }\n }\n\n /**\n * Validate that a path exists and is a directory\n */\n static validate(path: string): boolean {\n try {\n const stats = statSync(path);\n return stats.isDirectory();\n } catch {\n return false;\n }\n }\n}\n","export interface EmbeddingConfig {\n readonly model: string;\n readonly batchSize: number;\n readonly dimensions: number;\n}\n\nexport interface IndexingConfig {\n readonly concurrency: number;\n readonly chunkSize: number;\n readonly chunkOverlap: number;\n readonly ignorePatterns: readonly string[];\n}\n\nexport interface SearchConfig {\n readonly defaultMode: 'vector' | 'fts' | 'hybrid';\n readonly defaultLimit: number;\n readonly minScore: number;\n readonly rrf: {\n readonly k: number;\n readonly vectorWeight: number;\n readonly ftsWeight: number;\n };\n}\n\nexport interface CrawlConfig {\n readonly userAgent: string;\n readonly timeout: number;\n readonly maxConcurrency: number;\n}\n\nexport interface ServerConfig {\n readonly port: number;\n readonly host: string;\n}\n\nexport interface AppConfig {\n readonly version: number;\n readonly dataDir: string;\n readonly embedding: EmbeddingConfig;\n readonly indexing: IndexingConfig;\n readonly search: SearchConfig;\n readonly crawl: CrawlConfig;\n readonly server: ServerConfig;\n}\n\nexport const DEFAULT_CONFIG: AppConfig = {\n version: 1,\n dataDir: '.bluera/bluera-knowledge/data',\n embedding: {\n model: 'Xenova/all-MiniLM-L6-v2',\n batchSize: 32,\n dimensions: 384,\n },\n indexing: {\n concurrency: 4,\n chunkSize: 1000,\n chunkOverlap: 150,\n ignorePatterns: ['node_modules/**', '.git/**', '*.min.js', '*.map'],\n },\n search: {\n defaultMode: 'hybrid',\n defaultLimit: 10,\n minScore: 0.5,\n rrf: {\n k: 40,\n vectorWeight: 0.7,\n ftsWeight: 0.3,\n },\n },\n crawl: {\n userAgent: 'BlueraKnowledge/1.0',\n timeout: 30000,\n maxConcurrency: 3,\n },\n server: {\n port: 3847,\n host: '127.0.0.1',\n },\n};\n","import { createHash } from 'node:crypto';\nimport { readFile, readdir } from 'node:fs/promises';\nimport { join, extname, basename } from 'node:path';\nimport { ChunkingService } from './chunking.service.js';\nimport { createLogger } from '../logging/index.js';\nimport { createDocumentId } from '../types/brands.js';\nimport { ok, err } from '../types/result.js';\nimport type { CodeGraphService } from './code-graph.service.js';\nimport type { EmbeddingEngine } from '../db/embeddings.js';\nimport type { LanceStore } from '../db/lance.js';\nimport type { Document } from '../types/document.js';\nimport type { ProgressCallback } from '../types/progress.js';\nimport type { Result } from '../types/result.js';\nimport type { Store, FileStore, RepoStore } from '../types/store.js';\n\nconst logger = createLogger('index-service');\n\ninterface IndexResult {\n documentsIndexed: number;\n chunksCreated: number;\n timeMs: number;\n}\n\ninterface IndexOptions {\n chunkSize?: number;\n chunkOverlap?: number;\n codeGraphService?: CodeGraphService;\n}\n\nconst TEXT_EXTENSIONS = new Set([\n '.txt',\n '.md',\n '.js',\n '.ts',\n '.jsx',\n '.tsx',\n '.json',\n '.yaml',\n '.yml',\n '.html',\n '.css',\n '.scss',\n '.less',\n '.py',\n '.rb',\n '.go',\n '.rs',\n '.java',\n '.c',\n '.cpp',\n '.h',\n '.hpp',\n '.sh',\n '.bash',\n '.zsh',\n '.sql',\n '.xml',\n]);\n\nexport class IndexService {\n private readonly lanceStore: LanceStore;\n private readonly embeddingEngine: EmbeddingEngine;\n private readonly chunker: ChunkingService;\n private readonly codeGraphService: CodeGraphService | undefined;\n\n constructor(\n lanceStore: LanceStore,\n embeddingEngine: EmbeddingEngine,\n options: IndexOptions = {}\n ) {\n this.lanceStore = lanceStore;\n this.embeddingEngine = embeddingEngine;\n this.chunker = new ChunkingService({\n chunkSize: options.chunkSize ?? 768,\n chunkOverlap: options.chunkOverlap ?? 100,\n });\n this.codeGraphService = options.codeGraphService;\n }\n\n async indexStore(store: Store, onProgress?: ProgressCallback): Promise<Result<IndexResult>> {\n logger.info(\n {\n storeId: store.id,\n storeName: store.name,\n storeType: store.type,\n },\n 'Starting store indexing'\n );\n\n try {\n if (store.type === 'file' || store.type === 'repo') {\n return await this.indexFileStore(store, onProgress);\n }\n\n logger.error(\n { storeId: store.id, storeType: store.type },\n 'Unsupported store type for indexing'\n );\n return err(new Error(`Indexing not supported for store type: ${store.type}`));\n } catch (error) {\n logger.error(\n {\n storeId: store.id,\n error: error instanceof Error ? error.message : String(error),\n },\n 'Store indexing failed'\n );\n return err(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private async indexFileStore(\n store: FileStore | RepoStore,\n onProgress?: ProgressCallback\n ): Promise<Result<IndexResult>> {\n const startTime = Date.now();\n const files = await this.scanDirectory(store.path);\n const documents: Document[] = [];\n let filesProcessed = 0;\n\n logger.debug(\n {\n storeId: store.id,\n path: store.path,\n fileCount: files.length,\n },\n 'Files scanned for indexing'\n );\n\n // Collect source files for code graph building\n const sourceFiles: Array<{ path: string; content: string }> = [];\n\n // Emit start event\n onProgress?.({\n type: 'start',\n current: 0,\n total: files.length,\n message: 'Starting index',\n });\n\n for (const filePath of files) {\n const content = await readFile(filePath, 'utf-8');\n const fileHash = createHash('md5').update(content).digest('hex');\n // Pass file path for semantic Markdown chunking\n const chunks = this.chunker.chunk(content, filePath);\n\n // Determine file type for ranking\n const ext = extname(filePath).toLowerCase();\n const fileName = basename(filePath).toLowerCase();\n const fileType = this.classifyFileType(ext, fileName, filePath);\n\n // Collect source files for code graph\n if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {\n sourceFiles.push({ path: filePath, content });\n }\n\n for (const chunk of chunks) {\n const vector = await this.embeddingEngine.embed(chunk.content);\n const chunkId =\n chunks.length > 1\n ? `${store.id}-${fileHash}-${String(chunk.chunkIndex)}`\n : `${store.id}-${fileHash}`;\n\n const doc: Document = {\n id: createDocumentId(chunkId),\n content: chunk.content,\n vector,\n metadata: {\n type: chunks.length > 1 ? 'chunk' : 'file',\n storeId: store.id,\n path: filePath,\n indexedAt: new Date(),\n fileHash,\n chunkIndex: chunk.chunkIndex,\n totalChunks: chunk.totalChunks,\n // New metadata for ranking\n fileType,\n sectionHeader: chunk.sectionHeader,\n functionName: chunk.functionName,\n hasDocComments: /\\/\\*\\*[\\s\\S]*?\\*\\//.test(chunk.content),\n docSummary: chunk.docSummary,\n },\n };\n documents.push(doc);\n }\n filesProcessed++;\n\n // Emit progress event\n onProgress?.({\n type: 'progress',\n current: filesProcessed,\n total: files.length,\n message: `Indexing ${filePath}`,\n });\n }\n\n if (documents.length > 0) {\n await this.lanceStore.addDocuments(store.id, documents);\n }\n\n // Build and save code graph if service is available and we have source files\n if (this.codeGraphService && sourceFiles.length > 0) {\n const graph = await this.codeGraphService.buildGraph(sourceFiles);\n await this.codeGraphService.saveGraph(store.id, graph);\n }\n\n // Emit complete event\n onProgress?.({\n type: 'complete',\n current: files.length,\n total: files.length,\n message: 'Indexing complete',\n });\n\n const timeMs = Date.now() - startTime;\n\n logger.info(\n {\n storeId: store.id,\n storeName: store.name,\n documentsIndexed: filesProcessed,\n chunksCreated: documents.length,\n sourceFilesForGraph: sourceFiles.length,\n timeMs,\n },\n 'Store indexing complete'\n );\n\n return ok({\n documentsIndexed: filesProcessed,\n chunksCreated: documents.length,\n timeMs,\n });\n }\n\n private async scanDirectory(dir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Skip common ignored directories\n if (!['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {\n files.push(...(await this.scanDirectory(fullPath)));\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).toLowerCase();\n if (TEXT_EXTENSIONS.has(ext)) {\n files.push(fullPath);\n }\n }\n }\n\n return files;\n }\n\n /**\n * Classify file type for ranking purposes.\n * Documentation files rank higher than source code for documentation queries.\n * Phase 4: Enhanced to detect internal implementation files.\n */\n private classifyFileType(ext: string, fileName: string, filePath: string): string {\n // Documentation files\n if (ext === '.md') {\n // CHANGELOG files get their own category for intent-based penalties\n if (fileName === 'changelog.md' || fileName === 'changes.md' || /changelog/i.test(fileName)) {\n return 'changelog';\n }\n // Special doc files get highest priority\n if (['readme.md', 'migration.md', 'contributing.md'].includes(fileName)) {\n return 'documentation-primary';\n }\n // Check path for documentation indicators\n if (/\\/(docs?|documentation|guides?|tutorials?|articles?)\\//i.test(filePath)) {\n return 'documentation';\n }\n return 'documentation';\n }\n\n // Test files\n if (/\\.(test|spec)\\.[jt]sx?$/.test(fileName) || /\\/__tests__\\//.test(filePath)) {\n return 'test';\n }\n\n // Example files\n if (/\\/examples?\\//.test(filePath) || fileName.includes('example')) {\n return 'example';\n }\n\n // Config files\n if (/^(tsconfig|package|\\.eslint|\\.prettier|vite\\.config|next\\.config)/i.test(fileName)) {\n return 'config';\n }\n\n // Source code - distinguish between internal and public-facing\n if (['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.java'].includes(ext)) {\n // Internal implementation files (monorepo packages, lib internals)\n // These patterns indicate internal/core implementation code\n if (this.isInternalImplementation(filePath, fileName)) {\n return 'source-internal';\n }\n return 'source';\n }\n\n return 'other';\n }\n\n /**\n * Detect if a source file is internal implementation code.\n * Internal code should rank lower than public-facing APIs and docs.\n */\n private isInternalImplementation(filePath: string, fileName: string): boolean {\n const pathLower = filePath.toLowerCase();\n const fileNameLower = fileName.toLowerCase();\n\n // Monorepo internal packages (like Vue's packages/*/src/)\n if (/\\/packages\\/[^/]+\\/src\\//.test(pathLower)) {\n // Exception: index files often export public APIs\n if (fileNameLower === 'index.ts' || fileNameLower === 'index.js') {\n return false;\n }\n return true;\n }\n\n // Internal/core directories\n if (/\\/(internal|lib\\/core|core\\/src|_internal|private)\\//.test(pathLower)) {\n return true;\n }\n\n // Compiler/transform internals (often not what users want)\n if (\n /\\/(compiler|transforms?|parse|codegen)\\//.test(pathLower) &&\n !fileNameLower.includes('readme') &&\n !fileNameLower.includes('index')\n ) {\n return true;\n }\n\n return false;\n }\n}\n\n/**\n * Classify web content type based on URL patterns and page title.\n * Used for ranking boosts similar to local file classification.\n */\nexport function classifyWebContentType(url: string, title?: string): string {\n const urlLower = url.toLowerCase();\n const titleLower = (title ?? '').toLowerCase();\n\n // API reference documentation → documentation-primary (1.8x boost)\n if (\n /\\/api[-/]?(ref|reference|docs?)?\\//i.test(urlLower) ||\n /api\\s*(reference|documentation)/i.test(titleLower)\n ) {\n return 'documentation-primary';\n }\n\n // Getting started / tutorials → documentation-primary (1.8x boost)\n if (\n /\\/(getting[-_]?started|quickstart|tutorial|setup)\\b/i.test(urlLower) ||\n /(getting started|quickstart|tutorial)/i.test(titleLower)\n ) {\n return 'documentation-primary';\n }\n\n // General docs paths → documentation (1.5x boost)\n if (/\\/(docs?|documentation|reference|learn|manual|guide)/i.test(urlLower)) {\n return 'documentation';\n }\n\n // Examples and demos → example (1.4x boost)\n if (/\\/(examples?|demos?|samples?|cookbook)/i.test(urlLower)) {\n return 'example';\n }\n\n // Changelog → changelog (special handling in intent boosts)\n if (/changelog|release[-_]?notes/i.test(urlLower)) {\n return 'changelog';\n }\n\n // Blog posts → lower priority\n if (/\\/blog\\//i.test(urlLower)) {\n return 'other';\n }\n\n // Web content without specific path indicators is treated as documentation\n return 'documentation';\n}\n","export interface ChunkConfig {\n chunkSize: number;\n chunkOverlap: number;\n}\n\nexport interface Chunk {\n content: string;\n chunkIndex: number;\n totalChunks: number;\n startOffset: number;\n endOffset: number;\n /** Section header if this chunk starts a markdown section */\n sectionHeader?: string | undefined;\n /** Function or class name if this chunk contains a code declaration */\n functionName?: string | undefined;\n /** JSDoc/comment summary extracted from this chunk */\n docSummary?: string | undefined;\n}\n\n/**\n * Preset configurations for different content types.\n * Code uses smaller chunks for precise symbol matching.\n * Web/docs use larger chunks to preserve prose context.\n */\nconst CHUNK_PRESETS = {\n code: { chunkSize: 768, chunkOverlap: 100 },\n web: { chunkSize: 1200, chunkOverlap: 200 },\n docs: { chunkSize: 1200, chunkOverlap: 200 },\n} as const;\n\nexport type ContentType = keyof typeof CHUNK_PRESETS;\n\nexport class ChunkingService {\n private readonly chunkSize: number;\n private readonly chunkOverlap: number;\n\n constructor(config: ChunkConfig) {\n this.chunkSize = config.chunkSize;\n this.chunkOverlap = config.chunkOverlap;\n }\n\n /**\n * Create a ChunkingService with preset configuration for a content type.\n * - 'code': Smaller chunks (768/100) for precise code symbol matching\n * - 'web': Larger chunks (1200/200) for web prose content\n * - 'docs': Larger chunks (1200/200) for documentation\n */\n static forContentType(type: ContentType): ChunkingService {\n return new ChunkingService(CHUNK_PRESETS[type]);\n }\n\n /**\n * Chunk text content. Uses semantic chunking for Markdown and code files,\n * falling back to sliding window for other content.\n */\n chunk(text: string, filePath?: string): Chunk[] {\n // Use semantic chunking for Markdown files\n if (filePath !== undefined && filePath !== '' && /\\.md$/i.test(filePath)) {\n return this.chunkMarkdown(text);\n }\n\n // Use semantic chunking for TypeScript/JavaScript files\n if (filePath !== undefined && filePath !== '' && /\\.(ts|tsx|js|jsx)$/i.test(filePath)) {\n return this.chunkCode(text);\n }\n\n return this.chunkSlidingWindow(text);\n }\n\n /**\n * Semantic chunking for Markdown files.\n * Splits on section headers to keep related content together.\n */\n private chunkMarkdown(text: string): Chunk[] {\n // Match markdown headers (# through ####)\n const headerRegex = /^(#{1,4})\\s+(.+)$/gm;\n const sections: Array<{ header: string; content: string; startOffset: number }> = [];\n\n let lastIndex = 0;\n let lastHeader = '';\n let match: RegExpExecArray | null;\n\n while ((match = headerRegex.exec(text)) !== null) {\n // Save previous section\n if (match.index > lastIndex) {\n const content = text.slice(lastIndex, match.index).trim();\n if (content) {\n sections.push({\n header: lastHeader,\n content: content,\n startOffset: lastIndex,\n });\n }\n }\n lastHeader = match[2] ?? '';\n lastIndex = match.index;\n }\n\n // Add final section\n const finalContent = text.slice(lastIndex).trim();\n if (finalContent) {\n sections.push({\n header: lastHeader,\n content: finalContent,\n startOffset: lastIndex,\n });\n }\n\n // If no sections found, fall back to sliding window\n if (sections.length === 0) {\n return this.chunkSlidingWindow(text);\n }\n\n // Convert sections to chunks, splitting large sections if needed\n const chunks: Chunk[] = [];\n\n for (const section of sections) {\n if (section.content.length <= this.chunkSize) {\n // Section fits in one chunk\n chunks.push({\n content: section.content,\n chunkIndex: chunks.length,\n totalChunks: 0,\n startOffset: section.startOffset,\n endOffset: section.startOffset + section.content.length,\n sectionHeader: section.header || undefined,\n });\n } else {\n // Split large section using sliding window\n const sectionChunks = this.chunkSlidingWindow(section.content);\n for (const subChunk of sectionChunks) {\n chunks.push({\n ...subChunk,\n chunkIndex: chunks.length,\n startOffset: section.startOffset + subChunk.startOffset,\n endOffset: section.startOffset + subChunk.endOffset,\n sectionHeader: section.header || undefined,\n });\n }\n }\n }\n\n // Set totalChunks\n for (const chunk of chunks) {\n chunk.totalChunks = chunks.length;\n }\n\n return chunks;\n }\n\n /**\n * Semantic chunking for TypeScript/JavaScript code files.\n * Splits on top-level declarations to keep functions/classes together.\n */\n private chunkCode(text: string): Chunk[] {\n // Match top-level declarations with optional JSDoc/comments before them\n const declarationRegex =\n /^(?:\\/\\*\\*[\\s\\S]*?\\*\\/\\s*)?(?:export\\s+)?(?:async\\s+)?(?:function|class|interface|type|const|let|var|enum)\\s+(\\w+)/gm;\n const declarations: Array<{ startOffset: number; endOffset: number; name?: string }> = [];\n\n let match: RegExpExecArray | null;\n while ((match = declarationRegex.exec(text)) !== null) {\n const name = match[1];\n const decl: { startOffset: number; endOffset: number; name?: string } = {\n startOffset: match.index,\n endOffset: match.index,\n };\n if (name !== undefined) {\n decl.name = name;\n }\n declarations.push(decl);\n }\n\n // If no declarations found, use sliding window\n if (declarations.length === 0) {\n return this.chunkSlidingWindow(text);\n }\n\n // Find end of each declaration using brace-aware boundary detection\n for (let i = 0; i < declarations.length; i++) {\n const currentDecl = declarations[i];\n const nextDecl = declarations[i + 1];\n if (currentDecl === undefined) continue;\n\n // For declarations that likely have braces (functions, classes, enums)\n // use smart boundary detection\n const declText = text.slice(currentDecl.startOffset);\n if (\n /^(?:\\/\\*\\*[\\s\\S]*?\\*\\/\\s*)?(?:export\\s+)?(?:async\\s+)?(?:function|class|enum)\\s+/m.test(\n declText\n )\n ) {\n const boundary = this.findDeclarationEnd(declText);\n if (boundary > 0) {\n currentDecl.endOffset = currentDecl.startOffset + boundary;\n } else {\n // Fall back to next declaration or EOF\n currentDecl.endOffset = nextDecl !== undefined ? nextDecl.startOffset : text.length;\n }\n } else {\n // For other declarations (interface, type, const, let, var), use next declaration or EOF\n currentDecl.endOffset = nextDecl !== undefined ? nextDecl.startOffset : text.length;\n }\n }\n\n const chunks: Chunk[] = [];\n\n for (const decl of declarations) {\n const content = text.slice(decl.startOffset, decl.endOffset).trim();\n\n if (content.length <= this.chunkSize) {\n // Declaration fits in one chunk\n chunks.push({\n content,\n chunkIndex: chunks.length,\n totalChunks: 0,\n startOffset: decl.startOffset,\n endOffset: decl.endOffset,\n functionName: decl.name,\n });\n } else {\n // Split large declaration with sliding window\n const declChunks = this.chunkSlidingWindow(content);\n for (const subChunk of declChunks) {\n chunks.push({\n ...subChunk,\n chunkIndex: chunks.length,\n startOffset: decl.startOffset + subChunk.startOffset,\n endOffset: decl.startOffset + subChunk.endOffset,\n functionName: decl.name,\n });\n }\n }\n }\n\n // Set totalChunks\n for (const chunk of chunks) {\n chunk.totalChunks = chunks.length;\n }\n\n return chunks.length > 0 ? chunks : this.chunkSlidingWindow(text);\n }\n\n /**\n * Find the end of a code declaration by counting braces while ignoring\n * braces inside strings and comments.\n * Returns the offset where the declaration ends, or -1 if not found.\n */\n private findDeclarationEnd(text: string): number {\n let braceCount = 0;\n let inString = false;\n let inSingleLineComment = false;\n let inMultiLineComment = false;\n let stringChar = '';\n let i = 0;\n let foundFirstBrace = false;\n\n // Find the first opening brace\n while (i < text.length) {\n const char = text[i];\n const nextChar = i + 1 < text.length ? text[i + 1] : '';\n\n // Handle comments\n if (!inString && !inMultiLineComment && char === '/' && nextChar === '/') {\n inSingleLineComment = true;\n i += 2;\n continue;\n }\n\n if (!inString && !inSingleLineComment && char === '/' && nextChar === '*') {\n inMultiLineComment = true;\n i += 2;\n continue;\n }\n\n if (inMultiLineComment && char === '*' && nextChar === '/') {\n inMultiLineComment = false;\n i += 2;\n continue;\n }\n\n if (inSingleLineComment && char === '\\n') {\n inSingleLineComment = false;\n i++;\n continue;\n }\n\n // Skip if in comment\n if (inSingleLineComment || inMultiLineComment) {\n i++;\n continue;\n }\n\n // Handle strings\n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = true;\n stringChar = char;\n i++;\n continue;\n }\n\n if (inString && char === '\\\\') {\n // Skip escaped character\n i += 2;\n continue;\n }\n\n if (inString && char === stringChar) {\n inString = false;\n stringChar = '';\n i++;\n continue;\n }\n\n // Skip if in string\n if (inString) {\n i++;\n continue;\n }\n\n // Count braces\n if (char === '{') {\n braceCount++;\n foundFirstBrace = true;\n } else if (char === '}') {\n braceCount--;\n if (foundFirstBrace && braceCount === 0) {\n // Found the closing brace\n return i + 1;\n }\n }\n\n i++;\n }\n\n // If we didn't find a complete declaration, return -1\n return -1;\n }\n\n /**\n * Traditional sliding window chunking for non-Markdown content.\n */\n private chunkSlidingWindow(text: string): Chunk[] {\n if (text.length <= this.chunkSize) {\n return [\n {\n content: text,\n chunkIndex: 0,\n totalChunks: 1,\n startOffset: 0,\n endOffset: text.length,\n },\n ];\n }\n\n const chunks: Chunk[] = [];\n const step = this.chunkSize - this.chunkOverlap;\n let start = 0;\n\n while (start < text.length) {\n const end = Math.min(start + this.chunkSize, text.length);\n chunks.push({\n content: text.slice(start, end),\n chunkIndex: chunks.length,\n totalChunks: 0,\n startOffset: start,\n endOffset: end,\n });\n start += step;\n if (end === text.length) break;\n }\n\n // Set totalChunks\n for (const chunk of chunks) {\n chunk.totalChunks = chunks.length;\n }\n\n return chunks;\n }\n}\n","// Branded type symbols\ndeclare const StoreIdBrand: unique symbol;\ndeclare const DocumentIdBrand: unique symbol;\n\n// Branded types\nexport type StoreId = string & { readonly [StoreIdBrand]: typeof StoreIdBrand };\nexport type DocumentId = string & { readonly [DocumentIdBrand]: typeof DocumentIdBrand };\n\n// Valid ID pattern: alphanumeric, hyphens, underscores\nconst ID_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\nexport function isStoreId(value: string): value is StoreId {\n return value.length > 0 && ID_PATTERN.test(value);\n}\n\nexport function isDocumentId(value: string): value is DocumentId {\n return value.length > 0 && ID_PATTERN.test(value);\n}\n\nexport function createStoreId(value: string): StoreId {\n if (!isStoreId(value)) {\n throw new Error(`Invalid store ID: ${value}`);\n }\n return value;\n}\n\nexport function createDocumentId(value: string): DocumentId {\n if (!isDocumentId(value)) {\n throw new Error(`Invalid document ID: ${value}`);\n }\n return value;\n}\n","export interface CodeUnit {\n type: 'function' | 'class' | 'interface' | 'type' | 'const' | 'documentation' | 'example';\n name: string;\n signature: string;\n fullContent: string;\n startLine: number;\n endLine: number;\n language: string;\n}\n\nexport class CodeUnitService {\n extractCodeUnit(code: string, symbolName: string, language: string): CodeUnit | undefined {\n const lines = code.split('\\n');\n\n // Find the line containing the symbol\n let startLine = -1;\n let type: CodeUnit['type'] = 'function';\n\n // NOTE: Now supports function declarations, class declarations, and arrow functions (const/let/var).\n // Does not handle interfaces or type definitions yet.\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? '';\n\n if (line.includes(`function ${symbolName}`)) {\n startLine = i + 1; // 1-indexed\n type = 'function';\n break;\n }\n\n if (line.includes(`class ${symbolName}`)) {\n startLine = i + 1;\n type = 'class';\n break;\n }\n\n // Check for arrow functions: const/let/var name = ...\n if (line.match(new RegExp(`(?:const|let|var)\\\\s+${symbolName}\\\\s*=`))) {\n startLine = i + 1;\n type = 'const';\n break;\n }\n }\n\n if (startLine === -1) return undefined;\n\n // Find end line using state machine that tracks strings and comments\n let endLine = startLine;\n let braceCount = 0;\n let foundFirstBrace = false;\n\n // State machine for tracking context\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let inTemplateLiteral = false;\n let inMultiLineComment = false;\n\n for (let i = startLine - 1; i < lines.length; i++) {\n const line = lines[i] ?? '';\n let inSingleLineComment = false;\n\n for (let j = 0; j < line.length; j++) {\n const char = line[j];\n const prevChar = j > 0 ? line[j - 1] : '';\n const nextChar = j < line.length - 1 ? line[j + 1] : '';\n\n // Skip escaped characters within strings\n if (prevChar === '\\\\' && (inSingleQuote || inDoubleQuote || inTemplateLiteral)) {\n continue;\n }\n\n // Inside multi-line comment - only look for end marker\n if (inMultiLineComment) {\n if (char === '*' && nextChar === '/') {\n inMultiLineComment = false;\n j++; // Skip the /\n }\n continue;\n }\n\n // Inside single-line comment - skip rest of line\n if (inSingleLineComment) {\n continue;\n }\n\n // Inside a string - only look for closing delimiter\n if (inSingleQuote) {\n if (char === \"'\") inSingleQuote = false;\n continue;\n }\n if (inDoubleQuote) {\n if (char === '\"') inDoubleQuote = false;\n continue;\n }\n if (inTemplateLiteral) {\n if (char === '`') inTemplateLiteral = false;\n continue;\n }\n\n // Not inside any special context - check for context starters\n if (char === '/' && nextChar === '*') {\n inMultiLineComment = true;\n j++; // Skip the *\n continue;\n }\n if (char === '/' && nextChar === '/') {\n inSingleLineComment = true;\n continue;\n }\n if (char === \"'\") {\n inSingleQuote = true;\n continue;\n }\n if (char === '\"') {\n inDoubleQuote = true;\n continue;\n }\n if (char === '`') {\n inTemplateLiteral = true;\n continue;\n }\n\n // Count braces (we're not inside any string or comment)\n if (char === '{') {\n braceCount++;\n foundFirstBrace = true;\n }\n if (char === '}') braceCount--;\n }\n\n if (foundFirstBrace && braceCount === 0) {\n endLine = i + 1;\n break;\n }\n }\n\n const fullContent = lines.slice(startLine - 1, endLine).join('\\n');\n\n // Extract signature (first line, cleaned)\n const firstLine = lines[startLine - 1] ?? '';\n const signature = this.extractSignature(firstLine, symbolName, type);\n\n return {\n type,\n name: symbolName,\n signature,\n fullContent,\n startLine,\n endLine,\n language,\n };\n }\n\n private extractSignature(line: string, name: string, type: string): string {\n // Remove 'export', 'async', trim whitespace\n const sig = line\n .replace(/^\\s*export\\s+/, '')\n .replace(/^\\s*async\\s+/, '')\n .trim();\n\n if (type === 'function') {\n // Extract just \"functionName(params): returnType\"\n // Supports: simple types, generics (Promise<T>), arrays (T[]), unions (T | null)\n const match = sig.match(/function\\s+(\\w+\\([^)]*\\):\\s*[\\w<>[\\],\\s|]+)/);\n if (match?.[1] !== undefined && match[1].length > 0) return match[1].trim();\n }\n\n if (type === 'class') {\n return `class ${name}`;\n }\n\n if (type === 'const') {\n // For arrow functions, extract the variable declaration part\n // Example: const myFunc = (param: string): void => ...\n // Returns: const myFunc = (param: string): void\n const arrowMatch = sig.match(\n new RegExp(\n `((?:const|let|var)\\\\s+${name}\\\\s*=\\\\s*(?:async\\\\s+)?\\\\([^)]*\\\\)(?::\\\\s*[^=]+)?)`\n )\n );\n const matchedSig = arrowMatch?.[1];\n if (matchedSig !== undefined && matchedSig !== '') return matchedSig.trim();\n\n // Fallback for simple arrow functions without params\n return `const ${name}`;\n }\n\n return sig;\n }\n}\n","import { CodeUnitService } from './code-unit.service.js';\nimport { createLogger } from '../logging/index.js';\nimport type { CodeGraphService } from './code-graph.service.js';\nimport type { CodeGraph } from '../analysis/code-graph.js';\nimport type { EmbeddingEngine } from '../db/embeddings.js';\nimport type { LanceStore } from '../db/lance.js';\nimport type { StoreId } from '../types/brands.js';\nimport type {\n SearchQuery,\n SearchResponse,\n SearchResult,\n DetailLevel,\n CodeUnit,\n} from '../types/search.js';\n\nconst logger = createLogger('search-service');\n\n/**\n * Query intent classification for context-aware ranking.\n * Different intents prioritize different content types.\n */\nexport type QueryIntent = 'how-to' | 'implementation' | 'conceptual' | 'comparison' | 'debugging';\n\n/**\n * Classified intent with confidence score for multi-intent queries.\n */\nexport interface ClassifiedIntent {\n intent: QueryIntent;\n confidence: number;\n}\n\n/**\n * Intent-based file type multipliers - CONSERVATIVE version.\n * Applied on top of base file-type boosts.\n * Lessons learned: Too-aggressive penalties hurt when corpus lacks ideal content.\n * These values provide gentle guidance rather than dramatic reranking.\n */\nconst INTENT_FILE_BOOSTS: Record<QueryIntent, Record<string, number>> = {\n 'how-to': {\n 'documentation-primary': 1.3, // Strong boost for docs\n documentation: 1.2,\n example: 1.5, // Examples are ideal for \"how to\"\n source: 0.85, // Moderate penalty - source might still have good content\n 'source-internal': 0.7, // Stronger penalty - internal code less useful\n test: 0.8,\n config: 0.7,\n other: 0.9,\n },\n implementation: {\n 'documentation-primary': 0.95,\n documentation: 1.0,\n example: 1.0,\n source: 1.1, // Slight boost for source code\n 'source-internal': 1.05, // Internal code can be relevant\n test: 1.0,\n config: 0.95,\n other: 1.0,\n },\n conceptual: {\n 'documentation-primary': 1.1,\n documentation: 1.05,\n example: 1.0,\n source: 0.95,\n 'source-internal': 0.9,\n test: 0.9,\n config: 0.85,\n other: 0.95,\n },\n comparison: {\n 'documentation-primary': 1.15,\n documentation: 1.1,\n example: 1.05,\n source: 0.9,\n 'source-internal': 0.85,\n test: 0.9,\n config: 0.85,\n other: 0.95,\n },\n debugging: {\n 'documentation-primary': 1.0,\n documentation: 1.0,\n example: 1.05,\n source: 1.0, // Source code helps with debugging\n 'source-internal': 0.95,\n test: 1.05, // Tests can show expected behavior\n config: 0.9,\n other: 1.0,\n },\n};\n\n// Known frameworks/technologies for context-aware boosting\nconst FRAMEWORK_PATTERNS: Array<{ pattern: RegExp; terms: string[] }> = [\n { pattern: /\\bexpress\\b/i, terms: ['express', 'expressjs', 'express.js'] },\n { pattern: /\\bhono\\b/i, terms: ['hono'] },\n { pattern: /\\bzod\\b/i, terms: ['zod'] },\n { pattern: /\\breact\\b/i, terms: ['react', 'reactjs', 'react.js'] },\n { pattern: /\\bvue\\b/i, terms: ['vue', 'vuejs', 'vue.js', 'vue3'] },\n { pattern: /\\bnode\\b/i, terms: ['node', 'nodejs', 'node.js'] },\n { pattern: /\\btypescript\\b/i, terms: ['typescript', 'ts'] },\n { pattern: /\\bjwt\\b/i, terms: ['jwt', 'jsonwebtoken', 'json-web-token'] },\n];\n\n// Pattern definitions for intent classification\nconst HOW_TO_PATTERNS = [\n /how (do|can|should|would) (i|you|we)/i,\n /how to\\b/i,\n /what('s| is) the (best |right |correct )?(way|approach) to/i,\n /i (need|want|have) to/i,\n /show me how/i,\n /\\bwhat's the syntax\\b/i,\n /\\bhow do i (use|create|make|set up|configure|implement|add|get)\\b/i,\n /\\bi'm (trying|building|creating|making)\\b/i,\n];\n\nconst IMPLEMENTATION_PATTERNS = [\n /how (does|is) .* (implemented|work internally)/i,\n /\\binternal(ly)?\\b/i,\n /\\bsource code\\b/i,\n /\\bunder the hood\\b/i,\n /\\bimplementation (of|details?)\\b/i,\n];\n\nconst COMPARISON_PATTERNS = [\n /\\b(vs\\.?|versus)\\b/i,\n /\\bdifference(s)? between\\b/i,\n /\\bcompare\\b/i,\n /\\bshould (i|we) use .* or\\b/i,\n /\\bwhat's the difference\\b/i,\n /\\bwhich (one|is better)\\b/i,\n /\\bwhen (should|to) use\\b/i,\n];\n\nconst DEBUGGING_PATTERNS = [\n /\\b(error|bug|issue|problem|crash|fail|broken|wrong)\\b/i,\n /\\bdoesn't (work|compile|run)\\b/i,\n /\\bisn't (working|updating|rendering)\\b/i,\n /\\bwhy (is|does|doesn't|isn't)\\b/i,\n /\\bwhat('s| is) (wrong|happening|going on)\\b/i,\n /\\bwhat am i doing wrong\\b/i,\n /\\bnot (working|updating|showing)\\b/i,\n /\\bhow do i (fix|debug|solve|resolve)\\b/i,\n];\n\nconst CONCEPTUAL_PATTERNS = [\n /\\bwhat (is|are)\\b/i,\n /\\bexplain\\b/i,\n /\\bwhat does .* (mean|do)\\b/i,\n /\\bhow does .* work\\b/i,\n /\\bwhat('s| is) the (purpose|point|idea)\\b/i,\n];\n\n/**\n * Classify query intents with confidence scores.\n * Returns all matching intents, allowing queries to have multiple intents.\n */\nfunction classifyQueryIntents(query: string): ClassifiedIntent[] {\n const q = query.toLowerCase();\n const intents: ClassifiedIntent[] = [];\n\n // Check all pattern groups and add matching intents with confidence\n if (IMPLEMENTATION_PATTERNS.some((p) => p.test(q))) {\n intents.push({ intent: 'implementation', confidence: 0.9 });\n }\n\n if (DEBUGGING_PATTERNS.some((p) => p.test(q))) {\n intents.push({ intent: 'debugging', confidence: 0.85 });\n }\n\n if (COMPARISON_PATTERNS.some((p) => p.test(q))) {\n intents.push({ intent: 'comparison', confidence: 0.8 });\n }\n\n if (HOW_TO_PATTERNS.some((p) => p.test(q))) {\n intents.push({ intent: 'how-to', confidence: 0.75 });\n }\n\n if (CONCEPTUAL_PATTERNS.some((p) => p.test(q))) {\n intents.push({ intent: 'conceptual', confidence: 0.7 });\n }\n\n // If no patterns match, use how-to as the baseline intent\n if (intents.length === 0) {\n intents.push({ intent: 'how-to', confidence: 0.5 });\n }\n\n // Sort by confidence descending\n return intents.sort((a, b) => b.confidence - a.confidence);\n}\n\n/**\n * Get primary intent for logging/display purposes.\n */\nfunction getPrimaryIntent(intents: ClassifiedIntent[]): QueryIntent {\n return intents[0]?.intent ?? 'how-to';\n}\n\n/**\n * RRF presets for different content types.\n * Web/docs content uses higher k to reduce noise from repetitive structure.\n */\nconst RRF_PRESETS = {\n code: { k: 20, vectorWeight: 0.6, ftsWeight: 0.4 },\n web: { k: 30, vectorWeight: 0.55, ftsWeight: 0.45 },\n} as const;\n\n/**\n * Detect if results are primarily web content (have urls vs file paths).\n */\nfunction detectContentType(results: SearchResult[]): 'web' | 'code' {\n const webCount = results.filter((r) => 'url' in r.metadata).length;\n return webCount > results.length / 2 ? 'web' : 'code';\n}\n\nexport class SearchService {\n private readonly lanceStore: LanceStore;\n private readonly embeddingEngine: EmbeddingEngine;\n private readonly codeUnitService: CodeUnitService;\n private readonly codeGraphService: CodeGraphService | undefined;\n private readonly graphCache: Map<string, CodeGraph | null>;\n\n constructor(\n lanceStore: LanceStore,\n embeddingEngine: EmbeddingEngine,\n codeGraphService?: CodeGraphService\n ) {\n this.lanceStore = lanceStore;\n this.embeddingEngine = embeddingEngine;\n this.codeUnitService = new CodeUnitService();\n this.codeGraphService = codeGraphService;\n this.graphCache = new Map();\n }\n\n /**\n * Load code graph for a store, with caching.\n * Returns null if no graph is available.\n */\n private async loadGraphForStore(storeId: StoreId): Promise<CodeGraph | null> {\n if (!this.codeGraphService) return null;\n\n const cached = this.graphCache.get(storeId);\n if (cached !== undefined) return cached;\n\n const graph = await this.codeGraphService.loadGraph(storeId);\n const result = graph ?? null;\n this.graphCache.set(storeId, result);\n return result;\n }\n\n async search(query: SearchQuery): Promise<SearchResponse> {\n const startTime = Date.now();\n const mode = query.mode ?? 'hybrid';\n const limit = query.limit ?? 10;\n const stores = query.stores ?? [];\n const detail = query.detail ?? 'minimal';\n const intents = classifyQueryIntents(query.query);\n const primaryIntent = getPrimaryIntent(intents);\n\n logger.debug(\n {\n query: query.query,\n mode,\n limit,\n stores,\n detail,\n intent: primaryIntent,\n intents,\n },\n 'Search query received'\n );\n\n let allResults: SearchResult[] = [];\n\n // Fetch more results than needed to allow for deduplication\n const fetchLimit = limit * 3;\n\n if (mode === 'vector') {\n allResults = await this.vectorSearch(query.query, stores, fetchLimit, query.threshold);\n } else if (mode === 'fts') {\n allResults = await this.ftsSearch(query.query, stores, fetchLimit);\n } else {\n // Hybrid: combine vector and FTS with RRF\n allResults = await this.hybridSearch(query.query, stores, fetchLimit, query.threshold);\n }\n\n // Deduplicate by source file - keep best chunk per source (considers query relevance)\n const dedupedResults = this.deduplicateBySource(allResults, query.query);\n const resultsToEnhance = dedupedResults.slice(0, limit);\n\n // Load code graphs for stores in results (for contextual/full detail levels)\n const graphs = new Map<string, CodeGraph | null>();\n if (detail === 'contextual' || detail === 'full') {\n const storeIds = new Set(resultsToEnhance.map((r) => r.metadata.storeId));\n for (const storeId of storeIds) {\n graphs.set(storeId, await this.loadGraphForStore(storeId));\n }\n }\n\n // Enhance results with progressive context\n const enhancedResults = resultsToEnhance.map((r) => {\n const graph = graphs.get(r.metadata.storeId) ?? null;\n return this.addProgressiveContext(r, query.query, detail, graph);\n });\n\n const timeMs = Date.now() - startTime;\n\n logger.info(\n {\n query: query.query,\n mode,\n resultCount: enhancedResults.length,\n dedupedFrom: allResults.length,\n intents: intents.map((i) => `${i.intent}(${i.confidence.toFixed(2)})`),\n timeMs,\n },\n 'Search complete'\n );\n\n return {\n query: query.query,\n mode,\n stores,\n results: enhancedResults,\n totalResults: enhancedResults.length,\n timeMs,\n };\n }\n\n /**\n * Deduplicate results by source file path.\n * Keeps the best chunk for each unique source, considering both score and query relevance.\n */\n private deduplicateBySource(results: SearchResult[], query: string): SearchResult[] {\n const bySource = new Map<string, SearchResult>();\n const queryTerms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 2);\n\n for (const result of results) {\n // Use file path as the source key (or url for web content, or id as last resort)\n const sourceKey = result.metadata.path ?? result.metadata.url ?? result.id;\n\n const existing = bySource.get(sourceKey);\n if (!existing) {\n bySource.set(sourceKey, result);\n } else {\n // Score-weighted relevance: accounts for fileType/framework boosts\n const existingTermCount = this.countQueryTerms(existing.content, queryTerms);\n const newTermCount = this.countQueryTerms(result.content, queryTerms);\n\n // Weight term count by score to account for ranking boosts\n const existingRelevance = existingTermCount * existing.score;\n const newRelevance = newTermCount * result.score;\n\n if (newRelevance > existingRelevance) {\n bySource.set(sourceKey, result);\n }\n }\n }\n\n // Return results sorted by score\n return Array.from(bySource.values()).sort((a, b) => b.score - a.score);\n }\n\n /**\n * Count how many query terms appear in the content.\n */\n private countQueryTerms(content: string, queryTerms: string[]): number {\n const lowerContent = content.toLowerCase();\n return queryTerms.filter((term) => lowerContent.includes(term)).length;\n }\n\n /**\n * Normalize scores to 0-1 range and optionally filter by threshold.\n * This ensures threshold values match displayed scores (UX consistency).\n *\n * Edge case handling:\n * - If there's only 1 result or all results have the same score, normalization\n * would make them all 1.0. In this case, we keep the raw scores to allow\n * threshold filtering to work meaningfully on absolute quality.\n */\n private normalizeAndFilterScores(results: SearchResult[], threshold?: number): SearchResult[] {\n if (results.length === 0) return [];\n\n // Sort by score descending\n const sorted = [...results].sort((a, b) => b.score - a.score);\n\n // Get score range for normalization\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n if (first === undefined || last === undefined) return [];\n\n const maxScore = first.score;\n const minScore = last.score;\n const range = maxScore - minScore;\n\n // Only normalize when there's meaningful score variation\n // If all scores are the same (range = 0), keep raw scores for threshold filtering\n const normalized =\n range > 0\n ? sorted.map((r) => ({\n ...r,\n score: Math.round(((r.score - minScore) / range) * 1000000) / 1000000,\n }))\n : sorted; // Keep raw scores when no variation (allows threshold to filter by quality)\n\n // Apply threshold filter on scores\n if (threshold !== undefined) {\n return normalized.filter((r) => r.score >= threshold);\n }\n\n return normalized;\n }\n\n private async vectorSearch(\n query: string,\n stores: readonly StoreId[],\n limit: number,\n threshold?: number\n ): Promise<SearchResult[]> {\n const queryVector = await this.embeddingEngine.embed(query);\n const results: SearchResult[] = [];\n\n for (const storeId of stores) {\n const hits = await this.lanceStore.search(storeId, queryVector, limit, threshold);\n results.push(\n ...hits.map((r) => ({\n id: r.id,\n score: r.score,\n content: r.content,\n metadata: r.metadata,\n }))\n );\n }\n\n // Normalize scores and apply threshold filter\n const normalized = this.normalizeAndFilterScores(results, threshold);\n return normalized.slice(0, limit);\n }\n\n private async ftsSearch(\n query: string,\n stores: readonly StoreId[],\n limit: number\n ): Promise<SearchResult[]> {\n const results: SearchResult[] = [];\n\n for (const storeId of stores) {\n const hits = await this.lanceStore.fullTextSearch(storeId, query, limit);\n results.push(\n ...hits.map((r) => ({\n id: r.id,\n score: r.score,\n content: r.content,\n metadata: r.metadata,\n }))\n );\n }\n\n return results.sort((a, b) => b.score - a.score).slice(0, limit);\n }\n\n private async hybridSearch(\n query: string,\n stores: readonly StoreId[],\n limit: number,\n threshold?: number\n ): Promise<SearchResult[]> {\n // Classify query intents for context-aware ranking (supports multiple intents)\n const intents = classifyQueryIntents(query);\n\n // Get both result sets (don't pass threshold - apply after RRF normalization)\n const [vectorResults, ftsResults] = await Promise.all([\n this.vectorSearch(query, stores, limit * 2),\n this.ftsSearch(query, stores, limit * 2),\n ]);\n\n // Build rank maps\n const vectorRanks = new Map<string, number>();\n const ftsRanks = new Map<string, number>();\n const allDocs = new Map<string, SearchResult>();\n\n vectorResults.forEach((r, i) => {\n vectorRanks.set(r.id, i + 1);\n allDocs.set(r.id, r);\n });\n\n ftsResults.forEach((r, i) => {\n ftsRanks.set(r.id, i + 1);\n if (!allDocs.has(r.id)) {\n allDocs.set(r.id, r);\n }\n });\n\n // Calculate RRF scores with file-type boosting and preserve ranking metadata\n const rrfScores: Array<{\n id: string;\n score: number;\n result: SearchResult;\n metadata: {\n vectorRank?: number;\n ftsRank?: number;\n vectorRRF: number;\n ftsRRF: number;\n fileTypeBoost: number;\n frameworkBoost: number;\n urlKeywordBoost: number;\n pathKeywordBoost: number;\n };\n }> = [];\n\n // Select RRF config based on content type (web vs code)\n const contentType = detectContentType([...allDocs.values()]);\n const { k, vectorWeight, ftsWeight } = RRF_PRESETS[contentType];\n\n for (const [id, result] of allDocs) {\n const vectorRank = vectorRanks.get(id) ?? Infinity;\n const ftsRank = ftsRanks.get(id) ?? Infinity;\n\n const vectorRRF = vectorRank !== Infinity ? vectorWeight / (k + vectorRank) : 0;\n const ftsRRF = ftsRank !== Infinity ? ftsWeight / (k + ftsRank) : 0;\n\n // Apply file-type boost (base + multi-intent-adjusted)\n const fileTypeBoost = this.getFileTypeBoost(\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n result.metadata['fileType'] as string | undefined,\n intents\n );\n\n // Apply framework context boost\n const frameworkBoost = this.getFrameworkContextBoost(query, result);\n\n // Apply URL keyword boost (helps \"troubleshooting\" find /troubleshooting pages)\n const urlKeywordBoost = this.getUrlKeywordBoost(query, result);\n\n // Apply path keyword boost (helps \"dispatcher\" find async_dispatcher.py)\n const pathKeywordBoost = this.getPathKeywordBoost(query, result);\n\n const metadata: {\n vectorRank?: number;\n ftsRank?: number;\n vectorRRF: number;\n ftsRRF: number;\n fileTypeBoost: number;\n frameworkBoost: number;\n urlKeywordBoost: number;\n pathKeywordBoost: number;\n } = {\n vectorRRF,\n ftsRRF,\n fileTypeBoost,\n frameworkBoost,\n urlKeywordBoost,\n pathKeywordBoost,\n };\n\n if (vectorRank !== Infinity) {\n metadata.vectorRank = vectorRank;\n }\n if (ftsRank !== Infinity) {\n metadata.ftsRank = ftsRank;\n }\n\n rrfScores.push({\n id,\n score:\n (vectorRRF + ftsRRF) *\n fileTypeBoost *\n frameworkBoost *\n urlKeywordBoost *\n pathKeywordBoost,\n result,\n metadata,\n });\n }\n\n // Sort by RRF score\n const sorted = rrfScores.sort((a, b) => b.score - a.score).slice(0, limit);\n\n // Normalize scores to 0-1 range for better interpretability\n let normalizedResults: SearchResult[];\n\n if (sorted.length > 0) {\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n if (first === undefined || last === undefined) {\n normalizedResults = sorted.map((r) => ({\n ...r.result,\n score: r.score,\n rankingMetadata: r.metadata,\n }));\n } else {\n const maxScore = first.score;\n const minScore = last.score;\n const range = maxScore - minScore;\n\n if (range > 0) {\n // Round to avoid floating point precision issues in threshold comparisons\n normalizedResults = sorted.map((r) => ({\n ...r.result,\n score: Math.round(((r.score - minScore) / range) * 1000000) / 1000000,\n rankingMetadata: r.metadata,\n }));\n } else {\n // All same score - keep raw scores (allows threshold to filter by quality)\n normalizedResults = sorted.map((r) => ({\n ...r.result,\n score: r.score,\n rankingMetadata: r.metadata,\n }));\n }\n }\n } else {\n normalizedResults = [];\n }\n\n // Apply threshold filter on normalized scores (UX consistency)\n if (threshold !== undefined) {\n return normalizedResults.filter((r) => r.score >= threshold);\n }\n\n return normalizedResults;\n }\n\n async searchAllStores(query: SearchQuery, storeIds: StoreId[]): Promise<SearchResponse> {\n return this.search({\n ...query,\n stores: storeIds,\n });\n }\n\n /**\n * Get a score multiplier based on file type and query intent.\n * Documentation files get a strong boost to surface them higher.\n * Phase 4: Strengthened boosts for better documentation ranking.\n * Phase 1: Intent-based adjustments for context-aware ranking.\n */\n private getFileTypeBoost(fileType: string | undefined, intents: ClassifiedIntent[]): number {\n // Base file-type boosts\n let baseBoost: number;\n switch (fileType) {\n case 'documentation-primary':\n baseBoost = 1.8; // README, guides get very strong boost\n break;\n case 'documentation':\n baseBoost = 1.5; // docs/, tutorials/ get strong boost\n break;\n case 'example':\n baseBoost = 1.4; // examples/, demos/ are highly valuable\n break;\n case 'source':\n baseBoost = 1.0; // Source code baseline\n break;\n case 'source-internal':\n baseBoost = 0.75; // Internal implementation files (not too harsh)\n break;\n case 'test':\n baseBoost = 0.7; // Tests significantly lower\n break;\n case 'config':\n baseBoost = 0.5; // Config files rarely answer questions\n break;\n default:\n baseBoost = 1.0;\n }\n\n // Blend intent-based multipliers weighted by confidence\n let weightedMultiplier = 0;\n let totalConfidence = 0;\n\n for (const { intent, confidence } of intents) {\n const intentBoosts = INTENT_FILE_BOOSTS[intent];\n const multiplier = intentBoosts[fileType ?? 'other'] ?? 1.0;\n weightedMultiplier += multiplier * confidence;\n totalConfidence += confidence;\n }\n\n const blendedMultiplier = totalConfidence > 0 ? weightedMultiplier / totalConfidence : 1.0;\n\n return baseBoost * blendedMultiplier;\n }\n\n /**\n * Get a score multiplier based on URL keyword matching.\n * Boosts results where URL path contains significant query keywords.\n * This helps queries like \"troubleshooting\" rank /troubleshooting pages first.\n */\n private getUrlKeywordBoost(query: string, result: SearchResult): number {\n const url = result.metadata.url;\n if (url === undefined || url === '') return 1.0;\n\n // Extract path segments from URL and normalize\n const urlPath = url.toLowerCase().replace(/[^a-z0-9]+/g, ' ');\n\n // Common stop words to filter from queries\n const stopWords = new Set([\n 'how',\n 'to',\n 'the',\n 'a',\n 'an',\n 'is',\n 'are',\n 'what',\n 'why',\n 'when',\n 'where',\n 'can',\n 'do',\n 'does',\n 'i',\n 'my',\n 'your',\n 'it',\n 'in',\n 'on',\n 'for',\n 'with',\n 'this',\n 'that',\n 'get',\n 'use',\n 'using',\n ]);\n\n // Extract meaningful query terms\n const queryTerms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 2 && !stopWords.has(t));\n\n if (queryTerms.length === 0) return 1.0;\n\n // Count matching terms in URL path\n const matchingTerms = queryTerms.filter((term) => urlPath.includes(term));\n\n if (matchingTerms.length === 0) return 1.0;\n\n // Boost based on proportion of matching terms\n // Single match: ~1.5, all terms match: ~2.0\n const matchRatio = matchingTerms.length / queryTerms.length;\n return 1.0 + 1.0 * matchRatio;\n }\n\n /**\n * Get a score multiplier based on file path keyword matching.\n * Boosts results where file path contains significant query keywords.\n * This helps queries like \"dispatcher\" rank async_dispatcher.py higher.\n */\n private getPathKeywordBoost(query: string, result: SearchResult): number {\n const path = result.metadata.path;\n if (path === undefined || path === '') return 1.0;\n\n // Extract path segments and normalize (split on slashes, dots, underscores, etc.)\n const pathSegments = path.toLowerCase().replace(/[^a-z0-9]+/g, ' ');\n\n // Common stop words to filter from queries\n const stopWords = new Set([\n 'how',\n 'to',\n 'the',\n 'a',\n 'an',\n 'is',\n 'are',\n 'what',\n 'why',\n 'when',\n 'where',\n 'can',\n 'do',\n 'does',\n 'i',\n 'my',\n 'your',\n 'it',\n 'in',\n 'on',\n 'for',\n 'with',\n 'this',\n 'that',\n 'get',\n 'use',\n 'using',\n ]);\n\n // Extract meaningful query terms\n const queryTerms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 2 && !stopWords.has(t));\n\n if (queryTerms.length === 0) return 1.0;\n\n // Count matching terms in file path\n const matchingTerms = queryTerms.filter((term) => pathSegments.includes(term));\n\n if (matchingTerms.length === 0) return 1.0;\n\n // Boost based on proportion of matching terms\n // Single match: ~1.5, all terms match: ~2.0\n const matchRatio = matchingTerms.length / queryTerms.length;\n return 1.0 + 1.0 * matchRatio;\n }\n\n /**\n * Get a score multiplier based on framework context.\n * If query mentions a framework, boost results from that framework's files.\n */\n private getFrameworkContextBoost(query: string, result: SearchResult): number {\n const path = result.metadata.path ?? result.metadata.url ?? '';\n const content = result.content.toLowerCase();\n const pathLower = path.toLowerCase();\n\n // Check if query mentions any known frameworks\n for (const { pattern, terms } of FRAMEWORK_PATTERNS) {\n if (pattern.test(query)) {\n // Query mentions this framework - check if result is from that framework\n const resultMatchesFramework = terms.some(\n (term) => pathLower.includes(term) || content.includes(term)\n );\n\n if (resultMatchesFramework) {\n return 1.5; // Strong boost for matching framework\n } else {\n return 0.8; // Moderate penalty for non-matching when framework is specified\n }\n }\n }\n\n return 1.0; // No framework context in query\n }\n\n private addProgressiveContext(\n result: SearchResult,\n query: string,\n detail: DetailLevel,\n graph: CodeGraph | null\n ): SearchResult {\n const enhanced = { ...result };\n\n // Layer 1: Always add summary\n const path = result.metadata.path ?? result.metadata.url ?? 'unknown';\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const fileType = result.metadata['fileType'] as string | undefined;\n\n // Try to extract code unit\n const codeUnit = this.extractCodeUnitFromResult(result);\n const symbolName = codeUnit?.name ?? this.extractSymbolName(result.content);\n\n enhanced.summary = {\n type: this.inferType(fileType, codeUnit),\n name: symbolName,\n signature: codeUnit?.signature ?? '',\n purpose: this.generatePurpose(result.content, query),\n location: `${path}${codeUnit ? `:${String(codeUnit.startLine)}` : ''}`,\n relevanceReason: this.generateRelevanceReason(result, query),\n };\n\n // Layer 2: Add context if requested\n if (detail === 'contextual' || detail === 'full') {\n // Get usage stats from code graph if available\n const usage = this.getUsageFromGraph(graph, path, symbolName);\n\n enhanced.context = {\n interfaces: this.extractInterfaces(result.content),\n keyImports: this.extractImports(result.content),\n relatedConcepts: this.extractConcepts(result.content, query),\n usage,\n };\n }\n\n // Layer 3: Add full context if requested\n if (detail === 'full') {\n // Get related code from graph if available\n const relatedCode = this.getRelatedCodeFromGraph(graph, path, symbolName);\n\n enhanced.full = {\n completeCode: codeUnit?.fullContent ?? result.content,\n relatedCode,\n documentation: this.extractDocumentation(result.content),\n tests: undefined,\n };\n }\n\n return enhanced;\n }\n\n private extractCodeUnitFromResult(result: SearchResult): CodeUnit | undefined {\n const path = result.metadata.path;\n if (path === undefined || path === '') return undefined;\n\n const ext = path.split('.').pop() ?? '';\n const language =\n ext === 'ts' || ext === 'tsx'\n ? 'typescript'\n : ext === 'js' || ext === 'jsx'\n ? 'javascript'\n : ext;\n\n // Try to find a symbol name in the content\n const symbolName = this.extractSymbolName(result.content);\n if (symbolName === '') return undefined;\n\n return this.codeUnitService.extractCodeUnit(result.content, symbolName, language);\n }\n\n private extractSymbolName(content: string): string {\n // Extract function or class name\n const funcMatch = content.match(/(?:export\\s+)?(?:async\\s+)?function\\s+(\\w+)/);\n if (funcMatch?.[1] !== undefined && funcMatch[1] !== '') return funcMatch[1];\n\n const classMatch = content.match(/(?:export\\s+)?class\\s+(\\w+)/);\n if (classMatch?.[1] !== undefined && classMatch[1] !== '') return classMatch[1];\n\n const constMatch = content.match(/(?:export\\s+)?const\\s+(\\w+)/);\n if (constMatch?.[1] !== undefined && constMatch[1] !== '') return constMatch[1];\n\n // Fallback: return \"(anonymous)\" for unnamed symbols\n return '(anonymous)';\n }\n\n private inferType(\n fileType: string | undefined,\n codeUnit: CodeUnit | undefined\n ): import('../types/search.js').ResultSummary['type'] {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n if (codeUnit) return codeUnit.type as import('../types/search.js').ResultSummary['type'];\n if (fileType === 'documentation' || fileType === 'documentation-primary')\n return 'documentation';\n return 'function';\n }\n\n private generatePurpose(content: string, query: string): string {\n // Extract first line of JSDoc comment if present\n const docMatch = content.match(/\\/\\*\\*\\s*\\n\\s*\\*\\s*([^\\n]+)/);\n if (docMatch?.[1] !== undefined && docMatch[1] !== '') return docMatch[1].trim();\n\n const lines = content.split('\\n');\n const queryTerms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 2);\n\n // Helper to check if line is skippable (imports, declarations)\n const shouldSkip = (cleaned: string): boolean => {\n return (\n cleaned.startsWith('import ') ||\n cleaned.startsWith('export ') ||\n cleaned.startsWith('interface ') ||\n cleaned.startsWith('type ')\n );\n };\n\n // Helper to score a line based on query term matches\n const scoreLine = (cleaned: string): number => {\n const lowerLine = cleaned.toLowerCase();\n return queryTerms.filter((term) => lowerLine.includes(term)).length;\n };\n\n // Helper to check if line is meaningful (length, not a comment)\n const isMeaningful = (cleaned: string): boolean => {\n if (cleaned.length === 0) return false;\n if (cleaned.startsWith('//') || cleaned.startsWith('/*')) return false;\n // Accept Markdown headings\n if (cleaned.startsWith('#') && cleaned.length > 3) return true;\n // Accept lines 15+ chars\n return cleaned.length >= 15;\n };\n\n // First pass: find lines with query terms, preferring complete sentences\n let bestLine: string | null = null;\n let bestScore = 0;\n\n for (const line of lines) {\n const cleaned = line.trim();\n if (shouldSkip(cleaned) || !isMeaningful(cleaned)) continue;\n\n let score = scoreLine(cleaned);\n\n // Boost score for complete sentences (end with period, !, ?)\n if (/[.!?]$/.test(cleaned)) {\n score += 0.5;\n }\n\n // Boost score for code examples (contains function calls or assignments)\n // Favor complete patterns: function calls WITH arguments, assignments with values\n if (/\\w+\\([^)]*\\)|=\\s*\\w+\\(|=>/.test(cleaned)) {\n score += 0.6; // Enhanced boost to preserve code examples in snippets\n }\n\n if (score > bestScore) {\n bestScore = score;\n bestLine = cleaned;\n }\n }\n\n // If we found a line with query terms, use it\n if (bestLine !== null && bestLine !== '' && bestScore > 0) {\n if (bestLine.length > 150) {\n const firstSentence = bestLine.match(/^[^.!?]+[.!?]/);\n if (firstSentence && firstSentence[0].length >= 20 && firstSentence[0].length <= 150) {\n return firstSentence[0].trim();\n }\n return `${bestLine.substring(0, 147)}...`;\n }\n return bestLine;\n }\n\n // Fallback: first meaningful line (original logic)\n for (const line of lines) {\n const cleaned = line.trim();\n if (shouldSkip(cleaned) || !isMeaningful(cleaned)) continue;\n\n if (cleaned.length > 150) {\n const firstSentence = cleaned.match(/^[^.!?]+[.!?]/);\n if (firstSentence && firstSentence[0].length >= 20 && firstSentence[0].length <= 150) {\n return firstSentence[0].trim();\n }\n return `${cleaned.substring(0, 147)}...`;\n }\n\n return cleaned;\n }\n\n return 'Code related to query';\n }\n\n private generateRelevanceReason(result: SearchResult, query: string): string {\n const queryTerms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 2);\n const contentLower = result.content.toLowerCase();\n\n const matchedTerms = queryTerms.filter((term) => contentLower.includes(term));\n\n if (matchedTerms.length > 0) {\n return `Matches: ${matchedTerms.join(', ')}`;\n }\n\n return 'Semantically similar to query';\n }\n\n private extractInterfaces(content: string): string[] {\n const interfaces: string[] = [];\n const matches = content.matchAll(/interface\\s+(\\w+)/g);\n for (const match of matches) {\n if (match[1] !== undefined && match[1] !== '') interfaces.push(match[1]);\n }\n return interfaces;\n }\n\n private extractImports(content: string): string[] {\n const imports: string[] = [];\n const matches = content.matchAll(/import\\s+.*?from\\s+['\"]([^'\"]+)['\"]/g);\n for (const match of matches) {\n if (match[1] !== undefined && match[1] !== '') imports.push(match[1]);\n }\n return imports.slice(0, 5); // Top 5\n }\n\n private extractConcepts(content: string, _query: string): string[] {\n // TODO: Use _query parameter to prioritize query-related concepts in future enhancement\n\n // Common stopwords to filter out\n const stopwords = new Set([\n 'this',\n 'that',\n 'these',\n 'those',\n 'from',\n 'with',\n 'have',\n 'will',\n 'would',\n 'should',\n 'could',\n 'about',\n 'been',\n 'were',\n 'being',\n 'function',\n 'return',\n 'const',\n 'import',\n 'export',\n 'default',\n 'type',\n 'interface',\n 'class',\n 'extends',\n 'implements',\n 'async',\n 'await',\n 'then',\n 'catch',\n 'throw',\n 'error',\n 'undefined',\n 'null',\n 'true',\n 'false',\n 'void',\n 'number',\n 'string',\n 'boolean',\n 'object',\n 'array',\n 'promise',\n 'callback',\n 'resolve',\n 'reject',\n 'value',\n 'param',\n 'params',\n 'args',\n 'props',\n 'options',\n 'config',\n 'data',\n ]);\n\n // Simple keyword extraction\n const words = content.toLowerCase().match(/\\b[a-z]{4,}\\b/g) ?? [];\n const frequency = new Map<string, number>();\n\n for (const word of words) {\n // Skip stopwords\n if (stopwords.has(word)) continue;\n\n frequency.set(word, (frequency.get(word) ?? 0) + 1);\n }\n\n return Array.from(frequency.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([word]) => word);\n }\n\n private extractDocumentation(content: string): string {\n const docMatch = content.match(/\\/\\*\\*([\\s\\S]*?)\\*\\//);\n if (docMatch?.[1] !== undefined && docMatch[1] !== '') {\n return docMatch[1]\n .split('\\n')\n .map((line) => line.replace(/^\\s*\\*\\s?/, '').trim())\n .filter((line) => line.length > 0)\n .join('\\n');\n }\n return '';\n }\n\n /**\n * Get usage stats from code graph.\n * Returns default values if no graph is available.\n */\n private getUsageFromGraph(\n graph: CodeGraph | null,\n filePath: string,\n symbolName: string\n ): { calledBy: number; calls: number } {\n if (!graph || symbolName === '' || symbolName === '(anonymous)') {\n return { calledBy: 0, calls: 0 };\n }\n\n const nodeId = `${filePath}:${symbolName}`;\n return {\n calledBy: graph.getCalledByCount(nodeId),\n calls: graph.getCallsCount(nodeId),\n };\n }\n\n /**\n * Get related code from graph.\n * Returns callers and callees for the symbol.\n */\n private getRelatedCodeFromGraph(\n graph: CodeGraph | null,\n filePath: string,\n symbolName: string\n ): Array<{ file: string; summary: string; relationship: string }> {\n if (!graph || symbolName === '' || symbolName === '(anonymous)') {\n return [];\n }\n\n const nodeId = `${filePath}:${symbolName}`;\n const related: Array<{ file: string; summary: string; relationship: string }> = [];\n\n // Get callers (incoming edges)\n const incoming = graph.getIncomingEdges(nodeId);\n for (const edge of incoming) {\n if (edge.type === 'calls') {\n // Parse file:symbol from edge.from\n const [file, symbol] = this.parseNodeId(edge.from);\n related.push({\n file,\n summary: symbol ? `${symbol}()` : 'unknown',\n relationship: 'calls this',\n });\n }\n }\n\n // Get callees (outgoing edges)\n const outgoing = graph.getEdges(nodeId);\n for (const edge of outgoing) {\n if (edge.type === 'calls') {\n // Parse file:symbol from edge.to\n const [file, symbol] = this.parseNodeId(edge.to);\n related.push({\n file,\n summary: symbol ? `${symbol}()` : 'unknown',\n relationship: 'called by this',\n });\n }\n }\n\n // Limit to top 10 related items\n return related.slice(0, 10);\n }\n\n /**\n * Parse a node ID into file path and symbol name.\n */\n private parseNodeId(nodeId: string): [string, string] {\n const lastColon = nodeId.lastIndexOf(':');\n if (lastColon === -1) {\n return [nodeId, ''];\n }\n return [nodeId.substring(0, lastColon), nodeId.substring(lastColon + 1)];\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport { readFile, writeFile, mkdir, stat, access } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { cloneRepository } from '../plugin/git-clone.js';\nimport { createStoreId } from '../types/brands.js';\nimport { ok, err } from '../types/result.js';\nimport type { StoreId } from '../types/brands.js';\nimport type { Result } from '../types/result.js';\nimport type { Store, FileStore, RepoStore, WebStore, StoreType } from '../types/store.js';\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface CreateStoreInput {\n name: string;\n type: StoreType;\n path?: string | undefined;\n url?: string | undefined;\n description?: string | undefined;\n tags?: string[] | undefined;\n branch?: string | undefined;\n depth?: number | undefined;\n}\n\ninterface StoreRegistry {\n stores: Store[];\n}\n\nexport class StoreService {\n private readonly dataDir: string;\n private registry: StoreRegistry = { stores: [] };\n\n constructor(dataDir: string) {\n this.dataDir = dataDir;\n }\n\n async initialize(): Promise<void> {\n await mkdir(this.dataDir, { recursive: true });\n await this.loadRegistry();\n }\n\n async create(input: CreateStoreInput): Promise<Result<Store>> {\n if (!input.name || input.name.trim() === '') {\n return err(new Error('Store name cannot be empty'));\n }\n\n const existing = await this.getByName(input.name);\n if (existing !== undefined) {\n return err(new Error(`Store with name \"${input.name}\" already exists`));\n }\n\n const id = createStoreId(randomUUID());\n const now = new Date();\n\n let store: Store;\n\n switch (input.type) {\n case 'file': {\n if (input.path === undefined) {\n return err(new Error('Path is required for file stores'));\n }\n // Normalize path to absolute path (security: prevents path confusion)\n const normalizedPath = resolve(input.path);\n // Validate directory exists\n try {\n const stats = await stat(normalizedPath);\n if (!stats.isDirectory()) {\n return err(new Error(`Path is not a directory: ${normalizedPath}`));\n }\n } catch {\n return err(new Error(`Directory does not exist: ${normalizedPath}`));\n }\n store = {\n type: 'file',\n id,\n name: input.name,\n path: normalizedPath,\n description: input.description,\n tags: input.tags,\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n } satisfies FileStore;\n break;\n }\n\n case 'repo': {\n let repoPath = input.path;\n\n // If URL provided, clone it\n if (input.url !== undefined) {\n const cloneDir = join(this.dataDir, 'repos', id);\n const result = await cloneRepository({\n url: input.url,\n targetDir: cloneDir,\n ...(input.branch !== undefined ? { branch: input.branch } : {}),\n depth: input.depth ?? 1,\n });\n\n if (!result.success) {\n return err(result.error);\n }\n repoPath = result.data;\n }\n\n if (repoPath === undefined) {\n return err(new Error('Path or URL required for repo stores'));\n }\n\n // Normalize path to absolute path (security: prevents path confusion)\n const normalizedRepoPath = resolve(repoPath);\n\n store = {\n type: 'repo',\n id,\n name: input.name,\n path: normalizedRepoPath,\n url: input.url,\n branch: input.branch,\n description: input.description,\n tags: input.tags,\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n } satisfies RepoStore;\n break;\n }\n\n case 'web':\n if (input.url === undefined) {\n return err(new Error('URL is required for web stores'));\n }\n store = {\n type: 'web',\n id,\n name: input.name,\n url: input.url,\n depth: input.depth ?? 1,\n description: input.description,\n tags: input.tags,\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n } satisfies WebStore;\n break;\n }\n\n this.registry.stores.push(store);\n await this.saveRegistry();\n\n return ok(store);\n }\n\n async list(type?: StoreType): Promise<Store[]> {\n if (type !== undefined) {\n return Promise.resolve(this.registry.stores.filter((s) => s.type === type));\n }\n return Promise.resolve([...this.registry.stores]);\n }\n\n async get(id: StoreId): Promise<Store | undefined> {\n return Promise.resolve(this.registry.stores.find((s) => s.id === id));\n }\n\n async getByName(name: string): Promise<Store | undefined> {\n return Promise.resolve(this.registry.stores.find((s) => s.name === name));\n }\n\n async getByIdOrName(idOrName: string): Promise<Store | undefined> {\n return Promise.resolve(\n this.registry.stores.find((s) => s.id === idOrName || s.name === idOrName)\n );\n }\n\n async update(\n id: StoreId,\n updates: Partial<Pick<Store, 'name' | 'description' | 'tags'>>\n ): Promise<Result<Store>> {\n const index = this.registry.stores.findIndex((s) => s.id === id);\n if (index === -1) {\n return err(new Error(`Store not found: ${id}`));\n }\n\n const store = this.registry.stores[index];\n if (store === undefined) {\n return err(new Error(`Store not found: ${id}`));\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const updated = {\n ...store,\n ...updates,\n updatedAt: new Date(),\n } as Store;\n\n this.registry.stores[index] = updated;\n await this.saveRegistry();\n\n return ok(updated);\n }\n\n async delete(id: StoreId): Promise<Result<void>> {\n const index = this.registry.stores.findIndex((s) => s.id === id);\n if (index === -1) {\n return err(new Error(`Store not found: ${id}`));\n }\n\n this.registry.stores.splice(index, 1);\n await this.saveRegistry();\n\n return ok(undefined);\n }\n\n private async loadRegistry(): Promise<void> {\n const registryPath = join(this.dataDir, 'stores.json');\n const exists = await fileExists(registryPath);\n\n if (!exists) {\n // First run - create empty registry\n this.registry = { stores: [] };\n await this.saveRegistry();\n return;\n }\n\n // File exists - load it (throws on corruption per CLAUDE.md \"fail early\")\n const content = await readFile(registryPath, 'utf-8');\n try {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const data = JSON.parse(content) as { stores: Store[] };\n this.registry = {\n stores: data.stores.map((s) => ({\n ...s,\n id: createStoreId(s.id),\n createdAt: new Date(s.createdAt),\n updatedAt: new Date(s.updatedAt),\n })),\n };\n } catch (error) {\n throw new Error(\n `Failed to parse store registry at ${registryPath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n private async saveRegistry(): Promise<void> {\n const registryPath = join(this.dataDir, 'stores.json');\n await writeFile(registryPath, JSON.stringify(this.registry, null, 2));\n }\n}\n","import { spawn } from 'node:child_process';\nimport { mkdir } from 'node:fs/promises';\nimport { ok, err } from '../types/result.js';\nimport type { Result } from '../types/result.js';\n\nexport interface CloneOptions {\n url: string;\n targetDir: string;\n branch?: string;\n depth?: number;\n}\n\nexport async function cloneRepository(options: CloneOptions): Promise<Result<string>> {\n const { url, targetDir, branch, depth = 1 } = options;\n\n await mkdir(targetDir, { recursive: true });\n\n const args = ['clone', '--depth', String(depth)];\n if (branch !== undefined) {\n args.push('--branch', branch);\n }\n args.push(url, targetDir);\n\n return new Promise((resolve) => {\n const git = spawn('git', args, { stdio: ['ignore', 'pipe', 'pipe'] });\n\n let stderr = '';\n git.stderr.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n git.on('close', (code: number | null) => {\n if (code === 0) {\n resolve(ok(targetDir));\n } else {\n resolve(err(new Error(`Git clone failed: ${stderr}`)));\n }\n });\n });\n}\n\nexport function isGitUrl(source: string): boolean {\n return source.startsWith('http://') || source.startsWith('https://') || source.startsWith('git@');\n}\n\nexport function extractRepoName(url: string): string {\n const match = /\\/([^/]+?)(\\.git)?$/.exec(url);\n const name = match?.[1];\n if (name === undefined) {\n return 'repository';\n }\n return name;\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport { createInterface } from 'node:readline';\nimport { ZodError } from 'zod';\nimport {\n type CrawlResult,\n type HeadlessResult,\n type ParsePythonResult,\n type CrawledLink,\n validateCrawlResult,\n validateHeadlessResult,\n validateParsePythonResult,\n} from './schemas.js';\nimport { createLogger } from '../logging/index.js';\n\nconst logger = createLogger('python-bridge');\n\n// Re-export for backwards compatibility\nexport type { CrawledLink, ParsePythonResult };\n\ntype PendingResult = CrawlResult | HeadlessResult | ParsePythonResult;\n\ninterface PendingRequest {\n resolve: (v: PendingResult) => void;\n reject: (e: Error) => void;\n timeout: NodeJS.Timeout;\n method: 'crawl' | 'fetch_headless' | 'parse_python';\n}\n\nexport class PythonBridge {\n private process: ChildProcess | null = null;\n private readonly pending: Map<string, PendingRequest> = new Map();\n private stoppingIntentionally = false;\n\n start(): Promise<void> {\n if (this.process) return Promise.resolve();\n\n logger.debug('Starting Python bridge process');\n\n this.process = spawn('python3', ['python/crawl_worker.py'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Add error handler for process spawn errors\n this.process.on('error', (err) => {\n logger.error({ error: err.message, stack: err.stack }, 'Python bridge process error');\n this.rejectAllPending(new Error(`Process error: ${err.message}`));\n });\n\n // Add exit handler to detect non-zero exits\n this.process.on('exit', (code, signal) => {\n if (code !== 0 && code !== null) {\n logger.error({ code }, 'Python bridge process exited with non-zero code');\n this.rejectAllPending(new Error(`Process exited with code ${String(code)}`));\n } else if (signal && !this.stoppingIntentionally) {\n // Only log if we didn't intentionally stop the process\n logger.error({ signal }, 'Python bridge process killed with signal');\n this.rejectAllPending(new Error(`Process killed with signal ${signal}`));\n }\n this.process = null;\n this.stoppingIntentionally = false;\n });\n\n // Add stderr logging\n if (this.process.stderr) {\n const stderrRl = createInterface({ input: this.process.stderr });\n stderrRl.on('line', (line) => {\n logger.warn({ stderr: line }, 'Python bridge stderr output');\n });\n }\n\n if (this.process.stdout === null) {\n this.process.kill(); // Kill process to prevent zombie\n this.process = null; // Clean up reference\n return Promise.reject(new Error('Python bridge process stdout is null'));\n }\n const rl = createInterface({ input: this.process.stdout });\n rl.on('line', (line) => {\n // Filter out non-JSON lines (crawl4ai verbose output)\n if (!line.trim().startsWith('{')) {\n return;\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const response = JSON.parse(line) as {\n id: string;\n error?: { message: string };\n result?: PendingResult;\n };\n const pending = this.pending.get(response.id);\n if (pending !== undefined) {\n if (response.error !== undefined) {\n clearTimeout(pending.timeout);\n this.pending.delete(response.id);\n pending.reject(new Error(response.error.message));\n } else if (response.result !== undefined) {\n clearTimeout(pending.timeout);\n this.pending.delete(response.id);\n\n // Validate response structure based on method type\n try {\n let validated: PendingResult;\n if (pending.method === 'crawl') {\n validated = validateCrawlResult(response.result);\n } else if (pending.method === 'fetch_headless') {\n validated = validateHeadlessResult(response.result);\n } else {\n validated = validateParsePythonResult(response.result);\n }\n pending.resolve(validated);\n } catch (error: unknown) {\n // Log validation failure with original response for debugging\n if (error instanceof ZodError) {\n logger.error(\n {\n issues: error.issues,\n response: JSON.stringify(response.result),\n },\n 'Python bridge response validation failed'\n );\n pending.reject(\n new Error(`Invalid response format from Python bridge: ${error.message}`)\n );\n } else {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error({ error: errorMessage }, 'Response validation error');\n pending.reject(new Error(`Response validation error: ${errorMessage}`));\n }\n }\n }\n // If neither result nor error, leave pending (will timeout)\n }\n } catch (err) {\n logger.error(\n {\n error: err instanceof Error ? err.message : String(err),\n line,\n },\n 'Failed to parse JSON response from Python bridge'\n );\n }\n });\n\n return Promise.resolve();\n }\n\n async crawl(url: string, timeoutMs: number = 30000): Promise<CrawlResult> {\n if (!this.process) await this.start();\n\n const id = randomUUID();\n const request = {\n jsonrpc: '2.0',\n id,\n method: 'crawl',\n params: { url },\n };\n\n return new Promise((resolve, reject) => {\n // Set up timeout\n const timeout = setTimeout(() => {\n const pending = this.pending.get(id);\n if (pending) {\n this.pending.delete(id);\n reject(new Error(`Crawl timeout after ${String(timeoutMs)}ms for URL: ${url}`));\n }\n }, timeoutMs);\n\n this.pending.set(id, {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Promise resolve type narrowing\n resolve: resolve as (v: PendingResult) => void,\n reject,\n timeout,\n method: 'crawl',\n });\n if (!this.process?.stdin) {\n reject(new Error('Python bridge process not available'));\n return;\n }\n this.process.stdin.write(`${JSON.stringify(request)}\\n`);\n });\n }\n\n async fetchHeadless(url: string, timeoutMs: number = 60000): Promise<HeadlessResult> {\n if (!this.process) await this.start();\n\n const id = randomUUID();\n const request = {\n jsonrpc: '2.0',\n id,\n method: 'fetch_headless',\n params: { url },\n };\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n const pending = this.pending.get(id);\n if (pending) {\n this.pending.delete(id);\n reject(new Error(`Headless fetch timeout after ${String(timeoutMs)}ms for URL: ${url}`));\n }\n }, timeoutMs);\n\n this.pending.set(id, {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Promise resolve type narrowing\n resolve: resolve as (v: PendingResult) => void,\n reject,\n timeout,\n method: 'fetch_headless',\n });\n if (!this.process?.stdin) {\n reject(new Error('Python bridge process not available'));\n return;\n }\n this.process.stdin.write(`${JSON.stringify(request)}\\n`);\n });\n }\n\n async parsePython(\n code: string,\n filePath: string,\n timeoutMs: number = 10000\n ): Promise<ParsePythonResult> {\n if (!this.process) await this.start();\n\n const id = randomUUID();\n const request = {\n jsonrpc: '2.0',\n id,\n method: 'parse_python',\n params: { code, filePath },\n };\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n const pending = this.pending.get(id);\n if (pending) {\n this.pending.delete(id);\n reject(\n new Error(`Python parsing timeout after ${String(timeoutMs)}ms for file: ${filePath}`)\n );\n }\n }, timeoutMs);\n\n this.pending.set(id, {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Promise resolve type narrowing\n resolve: resolve as (v: PendingResult) => void,\n reject,\n timeout,\n method: 'parse_python',\n });\n if (!this.process?.stdin) {\n reject(new Error('Python bridge process not available'));\n return;\n }\n this.process.stdin.write(`${JSON.stringify(request)}\\n`);\n });\n }\n\n stop(): Promise<void> {\n if (!this.process) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.stoppingIntentionally = true;\n this.rejectAllPending(new Error('Python bridge stopped'));\n\n // Wait for process to actually exit before resolving\n const proc = this.process;\n if (proc === null) {\n resolve();\n return;\n }\n\n // Set up exit handler to resolve when process terminates\n const onExit = (): void => {\n resolve();\n };\n proc.once('exit', onExit);\n\n // Send SIGTERM to gracefully stop\n proc.kill();\n\n // Safety timeout in case process doesn't exit within 1 second\n setTimeout(() => {\n proc.removeListener('exit', onExit);\n if (this.process === proc) {\n proc.kill('SIGKILL'); // Force kill\n this.process = null;\n }\n resolve();\n }, 1000);\n });\n }\n\n private rejectAllPending(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n pending.reject(error);\n }\n this.pending.clear();\n }\n}\n","import { z } from 'zod';\n\n// Schema for crawl4ai link objects (matches CrawledLink interface)\n// This validates the actual runtime structure from Python\nexport const CrawledLinkSchema = z.object({\n href: z.string(),\n text: z.string(),\n title: z.string().optional(),\n base_domain: z.string().optional(),\n head_data: z.unknown().optional(),\n head_extraction_status: z.unknown().optional(),\n head_extraction_error: z.unknown().optional(),\n intrinsic_score: z.number().optional(),\n contextual_score: z.unknown().optional(),\n total_score: z.unknown().optional(),\n});\n\n// Schema for individual crawl page result\nconst CrawlPageSchema = z.object({\n url: z.string(),\n title: z.string(),\n content: z.string(),\n links: z.array(z.string()),\n crawledAt: z.string(),\n});\n\n// Schema for full crawl response\nexport const CrawlResultSchema = z.object({\n pages: z.array(CrawlPageSchema),\n});\n\n// Schema for headless fetch response\n// Supports both link objects and plain strings\nexport const HeadlessResultSchema = z.object({\n html: z.string(),\n markdown: z.string(),\n links: z.array(z.union([CrawledLinkSchema, z.string()])),\n});\n\n// Type exports derived from schemas (single source of truth)\nexport type CrawlResult = z.infer<typeof CrawlResultSchema>;\nexport type HeadlessResult = z.infer<typeof HeadlessResultSchema>;\nexport type CrawledLink = z.infer<typeof CrawledLinkSchema>;\n\n/**\n * Validates a headless fetch response from Python bridge.\n * Throws ZodError if the response doesn't match the expected schema.\n *\n * @param data - Raw data from Python bridge\n * @returns Validated HeadlessResult\n * @throws {z.ZodError} If validation fails\n */\nexport function validateHeadlessResult(data: unknown): HeadlessResult {\n return HeadlessResultSchema.parse(data);\n}\n\n/**\n * Validates a crawl response from Python bridge.\n * Throws ZodError if the response doesn't match the expected schema.\n *\n * @param data - Raw data from Python bridge\n * @returns Validated CrawlResult\n * @throws {z.ZodError} If validation fails\n */\nexport function validateCrawlResult(data: unknown): CrawlResult {\n return CrawlResultSchema.parse(data);\n}\n\n// Schema for Python AST parsing response\nconst MethodInfoSchema = z.object({\n name: z.string(),\n async: z.boolean(),\n signature: z.string(),\n startLine: z.number(),\n endLine: z.number(),\n calls: z.array(z.string()),\n});\n\nconst CodeNodeSchema = z.object({\n type: z.enum(['function', 'class']),\n name: z.string(),\n exported: z.boolean(),\n startLine: z.number(),\n endLine: z.number(),\n async: z.boolean().optional(),\n signature: z.string().optional(),\n calls: z.array(z.string()).optional(),\n methods: z.array(MethodInfoSchema).optional(),\n});\n\nconst ImportInfoSchema = z.object({\n source: z.string(),\n imported: z.string(),\n alias: z.string().optional().nullable(),\n});\n\nexport const ParsePythonResultSchema = z.object({\n nodes: z.array(CodeNodeSchema),\n imports: z.array(ImportInfoSchema),\n});\n\nexport type ParsePythonResult = z.infer<typeof ParsePythonResultSchema>;\n\n/**\n * Validates a Python AST parsing response from Python bridge.\n * Throws ZodError if the response doesn't match the expected schema.\n *\n * @param data - Raw data from Python bridge\n * @returns Validated ParsePythonResult\n * @throws {z.ZodError} If validation fails\n */\nexport function validateParsePythonResult(data: unknown): ParsePythonResult {\n return ParsePythonResultSchema.parse(data);\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { pipeline, env, type FeatureExtractionPipeline } from '@huggingface/transformers';\n\n// Set cache directory to ~/.cache/huggingface-transformers (outside node_modules)\n// This allows CI caching and prevents model re-downloads on each npm install\nenv.cacheDir = join(homedir(), '.cache', 'huggingface-transformers');\n\nexport class EmbeddingEngine {\n private extractor: FeatureExtractionPipeline | null = null;\n private readonly modelName: string;\n private readonly dimensions: number;\n\n constructor(modelName = 'Xenova/all-MiniLM-L6-v2', dimensions = 384) {\n this.modelName = modelName;\n this.dimensions = dimensions;\n }\n\n async initialize(): Promise<void> {\n if (this.extractor !== null) return;\n // @ts-expect-error TS2590: TypeScript can't represent the complex union type from pipeline()\n // This is a known limitation with @huggingface/transformers overloaded signatures\n this.extractor = await pipeline('feature-extraction', this.modelName, {\n dtype: 'fp32',\n });\n }\n\n async embed(text: string): Promise<number[]> {\n if (this.extractor === null) {\n await this.initialize();\n }\n if (this.extractor === null) {\n throw new Error('Failed to initialize embedding model');\n }\n const output = await this.extractor(text, {\n pooling: 'mean',\n normalize: true,\n });\n const result = Array.from(output.data);\n return result.map((v) => Number(v));\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n const BATCH_SIZE = 32; // Process 32 chunks in parallel\n const results: number[][] = [];\n\n for (let i = 0; i < texts.length; i += BATCH_SIZE) {\n const batch = texts.slice(i, i + BATCH_SIZE);\n\n // Process batch in parallel using Promise.all\n const batchResults = await Promise.all(batch.map((text) => this.embed(text)));\n\n results.push(...batchResults);\n\n // Small delay between batches to prevent memory issues\n if (i + BATCH_SIZE < texts.length) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n return results;\n }\n\n getDimensions(): number {\n return this.dimensions;\n }\n}\n","import * as lancedb from '@lancedb/lancedb';\nimport { createDocumentId } from '../types/brands.js';\nimport type { StoreId, DocumentId } from '../types/brands.js';\nimport type { Document, DocumentMetadata } from '../types/document.js';\nimport type { Table, Connection } from '@lancedb/lancedb';\n\ninterface LanceDocument {\n id: string;\n content: string;\n vector: number[];\n metadata: string; // JSON serialized\n [key: string]: unknown;\n}\n\ninterface SearchHit {\n id: string;\n content: string;\n metadata: string;\n _distance: number;\n}\n\nexport class LanceStore {\n private connection: Connection | null = null;\n private readonly tables: Map<string, Table> = new Map();\n private readonly dataDir: string;\n\n constructor(dataDir: string) {\n this.dataDir = dataDir;\n }\n\n async initialize(storeId: StoreId): Promise<void> {\n this.connection ??= await lancedb.connect(this.dataDir);\n\n const tableName = this.getTableName(storeId);\n const tableNames = await this.connection.tableNames();\n\n if (!tableNames.includes(tableName)) {\n // Create table with initial schema\n const table = await this.connection.createTable(tableName, [\n {\n id: '__init__',\n content: '',\n vector: new Array(384).fill(0),\n metadata: '{}',\n },\n ]);\n // Delete the init row\n await table.delete('id = \"__init__\"');\n this.tables.set(tableName, table);\n } else {\n const table = await this.connection.openTable(tableName);\n this.tables.set(tableName, table);\n }\n }\n\n async addDocuments(storeId: StoreId, documents: Document[]): Promise<void> {\n const table = await this.getTable(storeId);\n const lanceDocuments: LanceDocument[] = documents.map((doc) => ({\n id: doc.id,\n content: doc.content,\n vector: [...doc.vector],\n metadata: JSON.stringify(doc.metadata),\n }));\n await table.add(lanceDocuments);\n }\n\n async deleteDocuments(storeId: StoreId, documentIds: DocumentId[]): Promise<void> {\n const table = await this.getTable(storeId);\n const idList = documentIds.map((id) => `\"${id}\"`).join(', ');\n await table.delete(`id IN (${idList})`);\n }\n\n async search(\n storeId: StoreId,\n vector: number[],\n limit: number,\n // threshold is kept for API compatibility but filtering is done after normalization\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _threshold?: number\n ): Promise<\n Array<{ id: DocumentId; content: string; score: number; metadata: DocumentMetadata }>\n > {\n const table = await this.getTable(storeId);\n const query = table.vectorSearch(vector).limit(limit).distanceType('cosine');\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const results = (await query.toArray()) as SearchHit[];\n\n // Return all results - threshold filtering is applied after score normalization\n // in search.service.ts to match displayed scores\n return results.map((r) => ({\n id: createDocumentId(r.id),\n content: r.content,\n score: 1 - r._distance,\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n metadata: JSON.parse(r.metadata) as DocumentMetadata,\n }));\n }\n\n async createFtsIndex(storeId: StoreId): Promise<void> {\n const table = await this.getTable(storeId);\n await table.createIndex('content', {\n config: lancedb.Index.fts(),\n });\n }\n\n async fullTextSearch(\n storeId: StoreId,\n query: string,\n limit: number\n ): Promise<\n Array<{ id: DocumentId; content: string; score: number; metadata: DocumentMetadata }>\n > {\n const table = await this.getTable(storeId);\n\n try {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const results = (await table.search(query, 'fts').limit(limit).toArray()) as Array<{\n id: string;\n content: string;\n metadata: string;\n score: number;\n }>;\n\n return results.map((r) => ({\n id: createDocumentId(r.id),\n content: r.content,\n score: r.score,\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n metadata: JSON.parse(r.metadata) as DocumentMetadata,\n }));\n } catch {\n // FTS index may not exist, return empty\n return [];\n }\n }\n\n async deleteStore(storeId: StoreId): Promise<void> {\n const tableName = this.getTableName(storeId);\n if (this.connection !== null) {\n await this.connection.dropTable(tableName);\n this.tables.delete(tableName);\n }\n }\n\n close(): void {\n this.tables.clear();\n if (this.connection !== null) {\n this.connection.close();\n this.connection = null;\n }\n }\n\n /**\n * Async close that allows native code cleanup time.\n * Use this before process.exit() to prevent mutex crashes.\n */\n async closeAsync(): Promise<void> {\n this.tables.clear();\n if (this.connection !== null) {\n this.connection.close();\n this.connection = null;\n // Allow native threads time to complete cleanup\n // LanceDB's native code has background threads that need time\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n private getTableName(storeId: StoreId): string {\n return `documents_${storeId}`;\n }\n\n private async getTable(storeId: StoreId): Promise<Table> {\n const tableName = this.getTableName(storeId);\n let table = this.tables.get(tableName);\n if (table === undefined) {\n await this.initialize(storeId);\n table = this.tables.get(tableName);\n }\n if (table === undefined) {\n throw new Error(`Table not found for store: ${storeId}`);\n }\n return table;\n }\n}\n","import { CodeGraphService } from './code-graph.service.js';\nimport { ConfigService } from './config.service.js';\nimport { IndexService } from './index.service.js';\nimport { SearchService } from './search.service.js';\nimport { StoreService } from './store.service.js';\nimport { PythonBridge } from '../crawl/bridge.js';\nimport { EmbeddingEngine } from '../db/embeddings.js';\nimport { LanceStore } from '../db/lance.js';\nimport { createLogger, shutdownLogger } from '../logging/index.js';\n\nconst logger = createLogger('services');\n\nexport { ConfigService } from './config.service.js';\nexport { StoreService } from './store.service.js';\nexport { SearchService } from './search.service.js';\nexport { IndexService } from './index.service.js';\nexport { JobService } from './job.service.js';\nexport { WatchService } from './watch.service.js';\nexport { ChunkingService } from './chunking.service.js';\nexport { CodeGraphService } from './code-graph.service.js';\n\nexport interface ServiceContainer {\n config: ConfigService;\n store: StoreService;\n search: SearchService;\n index: IndexService;\n lance: LanceStore;\n embeddings: EmbeddingEngine;\n codeGraph: CodeGraphService;\n pythonBridge: PythonBridge;\n}\n\nexport async function createServices(\n configPath?: string,\n dataDir?: string,\n projectRoot?: string\n): Promise<ServiceContainer> {\n logger.info({ configPath, dataDir, projectRoot }, 'Initializing services');\n\n const config = new ConfigService(configPath, dataDir, projectRoot);\n const appConfig = await config.load();\n const resolvedDataDir = config.resolveDataDir();\n\n const lance = new LanceStore(resolvedDataDir);\n const embeddings = new EmbeddingEngine(appConfig.embedding.model, appConfig.embedding.dimensions);\n\n await embeddings.initialize();\n\n const store = new StoreService(resolvedDataDir);\n await store.initialize();\n\n const pythonBridge = new PythonBridge();\n await pythonBridge.start();\n\n const codeGraph = new CodeGraphService(resolvedDataDir, pythonBridge);\n const search = new SearchService(lance, embeddings, codeGraph);\n const index = new IndexService(lance, embeddings, { codeGraphService: codeGraph });\n\n logger.info({ dataDir: resolvedDataDir }, 'Services initialized successfully');\n\n return {\n config,\n store,\n search,\n index,\n lance,\n embeddings,\n codeGraph,\n pythonBridge,\n };\n}\n\n/**\n * Cleanly shut down all services, stopping background processes.\n * Call this after CLI commands complete to allow the process to exit.\n */\nexport async function destroyServices(services: ServiceContainer): Promise<void> {\n logger.info('Shutting down services');\n try {\n // Use async close to allow native threads time to cleanup\n await services.lance.closeAsync();\n } catch (e) {\n logger.error({ error: e }, 'Error closing LanceStore');\n }\n try {\n await services.pythonBridge.stop();\n } catch (e) {\n logger.error({ error: e }, 'Error stopping Python bridge');\n }\n await shutdownLogger();\n}\n"],"mappings":"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","names":["resolve","mkdirSync","existsSync","join","join","existsSync","mkdirSync","join","path","path","path","path","path","join","readFile","writeFile","mkdir","homedir","dirname","existsSync","dirname","join","path","path","homedir","readFile","mkdir","dirname","writeFile","createHash","readFile","join","readFile","createHash","join","logger","t","path","randomUUID","readFile","writeFile","mkdir","access","join","resolve","mkdir","mkdir","resolve","fileExists","path","access","mkdir","randomUUID","resolve","join","readFile","writeFile","spawn","randomUUID","logger","spawn","err","randomUUID","resolve","homedir","join","resolve","resolve","logger"]}
|