dsh-codebase-chat 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/context.ts","../src/tokenizer.ts","../src/indexer.ts","../src/extractor.ts","../src/merge-gaps.ts","../src/treesitter.ts","../src/embeddings.ts","../src/project.ts","../src/config.ts","../src/retriever.ts","../src/analysis.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\nimport { buildContext } from './context.js';\nimport { getIndex } from './indexer.js';\nimport { resolveProjectPath } from './project.js';\nimport { analyzeProject, formatHealthReport } from './analysis.js';\nimport { loadProjectConfig } from './config.js';\nimport { disposeTreeSitter } from './treesitter.js';\n\nclass ExitSignal {\n constructor(public code: number) {}\n}\n\nfunction exit(code: number): never {\n disposeTreeSitter();\n // Natural exit preferred (avoids a libuv assert while Emscripten handles\n // close); the unref'd timer only forces it if the loop stays alive.\n setTimeout(() => process.exit(code), 2000).unref();\n throw new ExitSignal(code);\n}\n\nfunction printHelp() {\n console.log(`\ndsh-codebase-chat CLI\n\nUsage:\n npx dsh-codebase-chat --project <path> --ask \"Explain auth flow\"\n npx dsh-codebase-chat --project <path> --search \"rate limiting\"\n npx dsh-codebase-chat --project <path> --file src/auth.ts\n npx dsh-codebase-chat --project <path> --index\n npx dsh-codebase-chat --project <path> --stats\n npx dsh-codebase-chat --project <path> --health\n\nOptions:\n -p, --project <path> Project directory (default: current directory)\n -a, --ask <question> Ask a question about the codebase\n -s, --search <query> Search code by semantic terms\n -f, --file <path> Focus on a specific file\n -i, --index Force re-index the project\n -t, --stats Print indexing stats\n -H, --health Deterministic static analysis (cycles, dead code, dupes, complexity)\n -e, --embed Enable local semantic embeddings (slower, more relevant)\n --lang <en|fr> Language for headings (default: .codebase-chat.json lang, else fr)\n -h, --help Show this help\n\nConfig:\n .codebase-chat.json Per-project settings: lang, maxTokens, ignoreDirs,\n ignoreFiles, ignoreGlobs, protectedPaths\n\nEnvironment:\n CODEBASE_CACHE_DIR Directory for the index cache\n`);\n}\n\nasync function main() {\n const { values } = parseArgs({\n options: {\n project: { type: 'string', short: 'p', default: '.' },\n ask: { type: 'string', short: 'a' },\n search: { type: 'string', short: 's' },\n file: { type: 'string', short: 'f' },\n index: { type: 'boolean', short: 'i', default: false },\n stats: { type: 'boolean', short: 't', default: false },\n health: { type: 'boolean', short: 'H', default: false },\n embed: { type: 'boolean', short: 'e', default: false },\n lang: { type: 'string' },\n help: { type: 'boolean', short: 'h', default: false },\n },\n allowPositionals: false,\n });\n\n if (values.help) {\n printHelp();\n exit(0);\n }\n\n const project = resolveProjectPath(values.project);\n const cfg = await loadProjectConfig(project);\n const lang = values.lang === 'en' || values.lang === 'fr' ? values.lang : (cfg.lang ?? 'fr');\n\n if (values.index) {\n await getIndex(project, m => console.log(m), true);\n exit(0);\n }\n\n if (values.stats) {\n const index = await getIndex(project, m => console.log(m));\n const fileCount = Object.keys(index.files).length;\n const totalTokens = Object.values(index.files).reduce((sum, f) => sum + f.chunks.reduce((s, c) => s + c.tokens, 0), 0);\n const termCount = Object.keys(index.terms).length;\n console.log(`Project: ${index.projectPath}`);\n console.log(`Files: ${fileCount}`);\n console.log(`Tokens: ${totalTokens}`);\n console.log(`Terms: ${termCount}`);\n console.log(`Cache: ${index.projectHash}`);\n exit(0);\n }\n\n if (values.health) {\n const report = await analyzeProject(project);\n console.log(formatHealthReport(report, lang));\n exit(0);\n }\n\n if (values.ask || values.search || values.file) {\n const result = await buildContext({\n project: values.project,\n query: values.ask ?? values.search ?? '',\n searchQuery: values.search,\n filePath: values.file,\n lang,\n embed: values.embed,\n });\n console.log(result.context);\n console.log(`\\n--- Stats ---`);\n console.log(`Project: ${result.absProject}`);\n console.log(`Chunks: ${result.chunks.length}`);\n console.log(`Tokens: ${result.tokenCount}`);\n exit(0);\n }\n\n printHelp();\n exit(1);\n}\n\nmain().catch(err => {\n disposeTreeSitter();\n if (err instanceof ExitSignal) {\n process.exitCode = err.code;\n return;\n }\n console.error(err?.message ?? err);\n process.exitCode = 1;\n setTimeout(() => process.exit(1), 2000).unref();\n});\n","import { join } from 'node:path';\r\nimport type { ContextOptions, ContextResult, CodeChunk } from './types.js';\r\nimport { countTokens, truncateToTokens } from './tokenizer.js';\r\nimport { embedIndex, getIndex } from './indexer.js';\r\nimport { scoreChunks, selectChunks } from './retriever.js';\r\nimport { findProjectRoot, resolveProjectPath, safeReadText } from './project.js';\r\nimport { loadProjectConfig } from './config.js';\r\n\r\nconst DEFAULT_MAX_TOKENS = 60_000;\r\nconst HEAD_BUDGET_TOKENS = 800;\r\n\r\ninterface Labels {\r\n project: string;\r\n focus: string;\r\n tree: string;\r\n noConstraints: string;\r\n constraints: string;\r\n answerIn: string;\r\n}\r\n\r\nfunction getLabels(lang: 'en' | 'fr'): Labels {\r\n return lang === 'en'\r\n ? {\r\n project: 'Project',\r\n focus: 'Focus',\r\n tree: 'File tree',\r\n noConstraints: 'No explicit constraints documented.',\r\n constraints: 'IDENTIFIED PRODUCT CONSTRAINTS',\r\n answerIn: 'Answer in English.',\r\n }\r\n : {\r\n project: 'Projet',\r\n focus: 'Focus',\r\n tree: 'Arborescence',\r\n noConstraints: 'Aucune contrainte explicite documentée.',\r\n constraints: 'CONTRAINTES PRODUIT IDENTIFIÉES',\r\n answerIn: 'Réponds obligatoirement en français.',\r\n };\r\n}\r\n\r\nasync function extractProductConstraints(absProject: string): Promise<string[]> {\r\n const candidates = ['README.md', 'README.MD', 'readme.md', 'MEMORY.md', 'CONTRIBUTING.md'];\r\n const constraints: string[] = [];\r\n for (const name of candidates) {\r\n const text = await safeReadText(join(absProject, name));\r\n if (!text) continue;\r\n const regex = /(?:constraint|contrainte|must|doit|interdit|forbidden|rule|règle|limitation)[\\s\\S]{0,200}/gi;\r\n let m;\r\n while ((m = regex.exec(text)) !== null) {\r\n const line = m[0].replace(/\\s+/g, ' ').trim();\r\n if (line.length > 20) constraints.push(`[${name}] ${line}`);\r\n }\r\n }\r\n return constraints.slice(0, 12);\r\n}\r\n\r\nfunction formatChunk(chunk: CodeChunk): string {\r\n const kind = chunk.kind.toUpperCase();\r\n const source = `[source: ${chunk.relPath}:${chunk.startLine}-${chunk.endLine}]`;\r\n const kindLabel = chunk.kind === 'unknown' ? '' : ` (${kind})`;\r\n const header = `--- ${chunk.relPath}${chunk.name ? ` :: ${chunk.name}` : ''}${kindLabel} ${source} ---`;\r\n return `${header}\\n${chunk.content}`;\r\n}\r\n\r\nexport async function buildContext(options: ContextOptions): Promise<ContextResult> {\r\n const { project, query, filePath, searchQuery, instruction, embed = false } = options;\r\n const absProject = await findProjectRoot(resolveProjectPath(project));\r\n const cfg = await loadProjectConfig(absProject);\r\n const maxTokens = options.maxTokens ?? cfg.maxTokens ?? DEFAULT_MAX_TOKENS;\r\n const lang = options.lang ?? cfg.lang ?? 'fr';\r\n const labels = getLabels(lang);\r\n const index = await getIndex(absProject);\r\n\r\n if (embed) {\r\n try {\r\n await embedIndex(index);\r\n } catch {\r\n // embeddings are optional: fallback to lexical if the model is unavailable\r\n }\r\n }\r\n\r\n const focus = filePath ?? searchQuery ?? query;\r\n\r\n let selectedChunks: CodeChunk[] = [];\r\n\r\n const bodyLimit = maxTokens - HEAD_BUDGET_TOKENS;\r\n const maxChunkTokens = Math.floor(bodyLimit / 2);\r\n\r\n if (filePath) {\r\n const all = Object.values(index.files);\r\n const target =\r\n all.find(f => f.relPath === filePath) ??\r\n all.filter(f => f.relPath.endsWith(`/${filePath}`) || f.relPath.endsWith(filePath))\r\n .sort((a, b) => a.relPath.length - b.relPath.length)[0];\r\n if (target) {\r\n const { chunks } = selectChunks(\r\n target.chunks.map(c => ({ ...c, score: 0 })),\r\n bodyLimit,\r\n Infinity\r\n );\r\n selectedChunks = chunks;\r\n } else {\r\n // Not a file path — treat it as a symbol/term and search instead of failing.\r\n const scored = await scoreChunks(index, filePath, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n if (chunks.length === 0) throw new Error(`File not found: ${filePath}`);\r\n selectedChunks = chunks;\r\n }\r\n } else if (searchQuery) {\r\n const scored = await scoreChunks(index, searchQuery, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n selectedChunks = chunks;\r\n } else {\r\n const scored = await scoreChunks(index, query, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n selectedChunks = chunks;\r\n }\r\n\r\n const constraints = await extractProductConstraints(absProject);\r\n const constraintsText = constraints.length\r\n ? `== ${labels.constraints} ==\\n${constraints.map(c => `- ${c}`).join('\\n')}`\r\n : `== ${labels.constraints} ==\\n${labels.noConstraints}`;\r\n\r\n const head = `${labels.project} : ${absProject}\\n${labels.focus} : ${focus}\\n${constraintsText}\\n\\n== ${labels.tree} ==\\n${index.tree}\\n`;\r\n const headTokens = countTokens(head);\r\n\r\n const body = selectedChunks.map(c => formatChunk(c)).join('\\n\\n');\r\n const bodyBudget = Math.max(0, maxTokens - headTokens - 100);\r\n const truncatedBody = truncateToTokens(body, bodyBudget);\r\n\r\n const baseInstruction = `${labels.answerIn}\\nAnswer the question or perform the requested task using the code context above. Cite every technical claim with [source: relative/path:line]. Provide confidence and severity where relevant.`;\r\n const finalInstruction = instruction ? `${instruction}\\n\\n${baseInstruction}` : baseInstruction;\r\n const prompt = `${head}\\n\\n${truncatedBody}\\n\\n${finalInstruction}`;\r\n\r\n const tokenCount = countTokens(prompt);\r\n\r\n return {\r\n absProject,\r\n context: prompt,\r\n chunks: selectedChunks,\r\n tokenCount,\r\n };\r\n}\r\n","import { encode, decode } from 'gpt-tokenizer';\r\n\r\n/**\r\n * Count the exact number of tokens for a given text using the CL100K base\r\n * tokenizer (used by GPT-4 / o1 / Claude / DeepSeek-v3).\r\n */\r\nexport function countTokens(text: string): number {\r\n return encode(text).length;\r\n}\r\n\r\n/**\r\n * Split a text into token chunks of at most `maxTokens`.\r\n * Tries to keep whole lines when possible.\r\n */\r\nexport function chunkByTokens(text: string, maxTokens: number, overlapTokens = 0): string[] {\r\n if (maxTokens <= 0) throw new RangeError('maxTokens must be positive');\r\n\r\n const tokens = encode(text);\r\n const chunks: string[] = [];\r\n const step = maxTokens - overlapTokens;\r\n\r\n for (let i = 0; i < tokens.length; i += step) {\r\n const end = Math.min(i + maxTokens, tokens.length);\r\n const slice = tokens.slice(i, end);\r\n chunks.push(decode(slice));\r\n if (end === tokens.length) break;\r\n }\r\n\r\n return chunks;\r\n}\r\n\r\n/**\r\n * Truncate a text to a maximum number of tokens, appending an ellipsis if truncated.\r\n */\r\nexport function truncateToTokens(text: string, maxTokens: number): string {\r\n const tokens = encode(text);\r\n if (tokens.length <= maxTokens) return text;\r\n const keep = Math.max(0, maxTokens - 5);\r\n const truncated = tokens.slice(0, keep);\r\n return `${decode(truncated)} [...]`;\r\n}\r\n","import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';\r\nimport { dirname, join, relative, sep } from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport type { CodeIndex, IndexedFile, InvertedIndex } from './types.js';\r\nimport { extractChunks } from './extractor.js';\r\nimport { ensureTreeSitterForExt } from './treesitter.js';\r\nimport { countTokens } from './tokenizer.js';\r\nimport { getEmbeddings } from './embeddings.js';\r\nimport {\r\n buildTree,\r\n cacheFilePath,\r\n fileHash,\r\n findProjectRoot,\r\n getWalkOptions,\r\n projectHash,\r\n resolveProjectPath,\r\n safeReadText,\r\n walkFiles,\r\n} from './project.js';\r\n\r\nconst INDEX_VERSION = 5;\r\n\r\nconst STOP_WORDS = new Set([\r\n 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought', 'used', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'and', 'or', 'but', 'so', 'yet', 'a', 'an', 'this', 'that', 'these', 'those', 'it', 'its', 'he', 'she', 'they', 'them', 'their', 'we', 'us', 'our', 'you', 'your', 'i', 'me', 'my', 'le', 'la', 'les', 'un', 'une', 'des', 'du', 'de', 'et', 'ou', 'que', 'qui', 'quoi', 'dont', 'ce', 'cet', 'cette', 'ces', 'est', 'sont', 'etait', 'etaient', 'avoir', 'etre', 'faire', 'dans', 'pour', 'sur', 'avec', 'par', 'a', 'au', 'aux'\r\n]);\r\n\r\nfunction tokenizeTerms(text: string): string[] {\r\n return text\r\n .replace(/[^a-zA-Z0-9\\u00C0-\\u017F]+/g, ' ')\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter(Boolean)\r\n .filter(t => t.length > 1 && !STOP_WORDS.has(t));\r\n}\r\n\r\nfunction buildInvertedIndex(files: Record<string, IndexedFile>): InvertedIndex {\r\n const index: InvertedIndex = {};\r\n for (const file of Object.values(files)) {\r\n for (const chunk of file.chunks) {\r\n const terms = new Set([\r\n ...tokenizeTerms(chunk.content),\r\n ...tokenizeTerms(chunk.relPath),\r\n ...tokenizeTerms(chunk.name ?? ''),\r\n ]);\r\n for (const term of terms) {\r\n if (!index[term]) index[term] = {};\r\n if (!index[term][file.relPath]) index[term][file.relPath] = 0;\r\n index[term][file.relPath] += 1;\r\n }\r\n }\r\n }\r\n return index;\r\n}\r\n\r\nexport async function loadIndex(projectPath: string): Promise<CodeIndex | null> {\r\n const absProject = await findProjectRoot(resolveProjectPath(projectPath));\r\n const p = cacheFilePath(absProject);\r\n if (!existsSync(p)) return null;\r\n try {\r\n const raw = await readFile(p, 'utf8');\r\n const data = JSON.parse(raw) as CodeIndex;\r\n if (data.version !== INDEX_VERSION) return null;\r\n return data;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport async function saveIndex(index: CodeIndex): Promise<void> {\r\n const p = cacheFilePath(index.projectPath);\r\n await mkdir(dirname(p), { recursive: true });\r\n await writeFile(p, JSON.stringify(index), 'utf8');\r\n}\r\n\r\nexport async function embedIndex(index: CodeIndex, progress?: (message: string) => void): Promise<void> {\r\n const allChunks = Object.values(index.files).flatMap(f => f.chunks);\r\n const missing = allChunks.filter(c => !c.embedding || c.embedding.length === 0);\r\n if (missing.length === 0) return;\r\n\r\n const batchSize = 32;\r\n for (let i = 0; i < missing.length; i += batchSize) {\r\n const batch = missing.slice(i, i + batchSize);\r\n progress?.(`Embedding ${i + batch.length}/${missing.length} chunks...`);\r\n try {\r\n const vectors = await getEmbeddings(batch.map(c => c.content));\r\n for (let j = 0; j < batch.length; j++) {\r\n batch[j].embedding = vectors[j];\r\n }\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n progress?.(`Embedding failed: ${msg}`);\r\n break;\r\n }\r\n }\r\n\r\n await saveIndex(index);\r\n}\r\n\r\nexport async function buildIndex(projectPath: string, progress?: (message: string) => void): Promise<CodeIndex> {\r\n const absProject = await findProjectRoot(resolveProjectPath(projectPath));\r\n const projectName = absProject.split(sep).pop() ?? 'project';\r\n\r\n progress?.(`Indexing ${projectName}...`);\r\n\r\n const walk = await getWalkOptions(absProject);\r\n const tree = await buildTree(absProject, undefined, walk.skipDirs);\r\n const startDir = absProject;\r\n const previous = await loadIndex(absProject);\r\n const previousFiles = previous?.projectPath === absProject ? previous.files : {};\r\n const files: Record<string, IndexedFile> = {};\r\n let totalTokens = 0;\r\n let reused = 0;\r\n\r\n for await (const fullPath of walkFiles(startDir, walk.skipDirs, walk.skipFiles, walk.ignoreGlobs)) {\r\n const relPath = relative(startDir, fullPath).split(sep).join('/');\r\n progress?.(`Reading ${relPath}`);\r\n\r\n const fstats = await stat(fullPath);\r\n\r\n // Reuse cached chunks when the file signature is unchanged (mtime + size).\r\n const cached = previousFiles[relPath];\r\n if (cached && cached.mtimeMs === fstats.mtimeMs && cached.size === fstats.size) {\r\n files[relPath] = cached;\r\n reused++;\r\n totalTokens += cached.chunks.reduce((sum, c) => sum + c.tokens, 0);\r\n continue;\r\n }\r\n\r\n const text = await safeReadText(fullPath);\r\n if (!text) continue;\r\n\r\n const hash = fileHash(fstats, text);\r\n\r\n // Lazy-load the tree-sitter grammar for this extension (cached after first call).\r\n const ext = relPath.slice(relPath.lastIndexOf('.')).toLowerCase();\r\n await ensureTreeSitterForExt(ext);\r\n\r\n const chunks = extractChunks(relPath, text).map(chunk => ({\r\n ...chunk,\r\n // recompute tokens to be safe\r\n tokens: countTokens(chunk.content),\r\n }));\r\n\r\n totalTokens += chunks.reduce((sum, c) => sum + c.tokens, 0);\r\n\r\n files[relPath] = {\r\n relPath,\r\n size: fstats.size,\r\n mtimeMs: fstats.mtimeMs,\r\n hash,\r\n chunks,\r\n };\r\n }\r\n\r\n const now = Date.now();\r\n const index: CodeIndex = {\r\n projectPath: absProject,\r\n projectHash: projectHash(absProject),\r\n version: INDEX_VERSION,\r\n createdAt: previous?.createdAt ?? now,\r\n updatedAt: now,\r\n tree,\r\n constraints: [],\r\n files,\r\n terms: buildInvertedIndex(files),\r\n };\r\n\r\n await saveIndex(index);\r\n progress?.(`Indexed ${Object.keys(files).length} files, ~${totalTokens} tokens${reused ? ` (${reused} unchanged reused)` : ''}`);\r\n return index;\r\n}\r\n\r\nexport async function getIndex(projectPath: string, progress?: (message: string) => void, force = false): Promise<CodeIndex> {\r\n const resolved = resolveProjectPath(projectPath);\r\n const absProject = await findProjectRoot(resolved);\r\n const existing = force ? null : await loadIndex(resolved);\r\n if (existing && existing.projectPath === absProject) {\r\n // Fast freshness check: mtime + size only, no file reads.\r\n let stale = false;\r\n for (const file of Object.values(existing.files)) {\r\n const fullPath = join(absProject, file.relPath);\r\n try {\r\n const fstats = await stat(fullPath);\r\n if (fstats.mtimeMs !== file.mtimeMs || fstats.size !== file.size) {\r\n stale = true;\r\n break;\r\n }\r\n } catch {\r\n stale = true;\r\n break;\r\n }\r\n }\r\n if (!stale) {\r\n progress?.('Loaded index from cache');\r\n return existing;\r\n }\r\n }\r\n return buildIndex(projectPath, progress);\r\n}\r\n\r\n\r\n","import { parse } from '@babel/parser';\r\nimport traverse from '@babel/traverse';\r\nimport * as t from '@babel/types';\r\nimport type { CodeChunk } from './types.js';\r\nimport { countTokens } from './tokenizer.js';\r\nimport { mergeGaps } from './merge-gaps.js';\r\nimport { extractWithTreeSitter, treeSitterReady } from './treesitter.js';\r\n\r\nconst JS_LIKE = new Set([\r\n '.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx'\r\n]);\r\n\r\ninterface BabelNode {\r\n loc?: { start: { line: number }; end: { line: number } } | null;\r\n}\r\n\r\nfunction getName(node: BabelNode & t.Node): string | undefined {\r\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isTSInterfaceDeclaration(node) || t.isTSTypeAliasDeclaration(node)) {\r\n return node.id?.name;\r\n }\r\n if (t.isVariableDeclaration(node)) {\r\n const first = node.declarations[0];\r\n if (first && t.isIdentifier(first.id)) return first.id.name;\r\n }\r\n if (t.isObjectMethod(node) || t.isClassMethod(node) || t.isClassPrivateMethod(node)) {\r\n const key = node.key as any;\r\n if (t.isIdentifier(node.key) || t.isStringLiteral(node.key) || t.isNumericLiteral(node.key)) {\r\n return String(key.name ?? key.value ?? 'anonymous');\r\n }\r\n if (t.isPrivateName(node.key)) {\r\n return (node.key.id as any)?.name;\r\n }\r\n }\r\n if (t.isExportNamedDeclaration(node) && node.declaration) {\r\n return getName(node.declaration as t.Node);\r\n }\r\n if (t.isExportDefaultDeclaration(node) && node.declaration) {\r\n if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {\r\n return getName(node.declaration) ?? 'default';\r\n }\r\n if (t.isVariableDeclaration(node.declaration)) {\r\n return getName(node.declaration) ?? 'default';\r\n }\r\n return 'default';\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction getKind(node: t.Node): CodeChunk['kind'] {\r\n if (t.isClassMethod(node) || t.isClassPrivateMethod(node) || t.isObjectMethod(node)) return 'method';\r\n if (t.isFunctionDeclaration(node) || t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) return 'function';\r\n if (t.isClassDeclaration(node) || t.isClassExpression(node)) return 'class';\r\n if (t.isTSInterfaceDeclaration(node) || t.isTSTypeAliasDeclaration(node)) return 'type';\r\n if (t.isImportDeclaration(node) || t.isExportAllDeclaration(node) || t.isExportNamespaceSpecifier(node)) return 'import';\r\n if (t.isVariableDeclaration(node)) return 'unknown';\r\n if (t.isExportNamedDeclaration(node) && node.declaration) return getKind(node.declaration);\r\n if (t.isExportDefaultDeclaration(node) && node.declaration) return getKind(node.declaration);\r\n if (t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node)) return 'import';\r\n return 'unknown';\r\n}\r\n\r\nfunction sliceLines(content: string, start: number, end: number): string {\r\n const lines = content.split('\\n');\r\n return lines.slice(start - 1, end).join('\\n');\r\n}\r\n\r\nfunction extractTopLevelWithBabel(relPath: string, content: string): CodeChunk[] {\r\n const ast = parse(content, {\r\n sourceType: 'module',\r\n allowImportExportEverywhere: true,\r\n allowReturnOutsideFunction: true,\r\n plugins: [\r\n 'typescript',\r\n 'jsx',\r\n 'decorators-legacy',\r\n 'classProperties',\r\n 'asyncGenerators',\r\n 'bigInt',\r\n 'dynamicImport',\r\n 'exportDefaultFrom',\r\n 'nullishCoalescingOperator',\r\n 'numericSeparator',\r\n 'objectRestSpread',\r\n 'optionalCatchBinding',\r\n 'optionalChaining',\r\n 'topLevelAwait',\r\n ] as any,\r\n });\r\n\r\n const chunks: CodeChunk[] = [];\r\n const visitedRanges: [number, number][] = [];\r\n\r\n traverse(ast, {\r\n enter(path) {\r\n const node = path.node;\r\n if (\r\n t.isFunctionDeclaration(node) ||\r\n t.isClassDeclaration(node) ||\r\n t.isTSInterfaceDeclaration(node) ||\r\n t.isTSTypeAliasDeclaration(node) ||\r\n t.isVariableDeclaration(node) ||\r\n t.isImportDeclaration(node) ||\r\n t.isExportNamedDeclaration(node) ||\r\n t.isExportDefaultDeclaration(node) ||\r\n t.isExportAllDeclaration(node)\r\n ) {\r\n const loc = node.loc;\r\n if (!loc) return;\r\n // Avoid duplicate nested traversal: only consider top-level declarations\r\n if (path.parentPath && !t.isProgram(path.parentPath.node)) return;\r\n\r\n // Class methods\r\n if (t.isClassDeclaration(node) && node.body?.body) {\r\n for (const member of node.body.body) {\r\n if (!member.loc) continue;\r\n if (t.isClassMethod(member) || t.isClassPrivateMethod(member) || t.isClassProperty(member)) {\r\n const methodChunk: CodeChunk = {\r\n relPath,\r\n startLine: member.loc.start.line,\r\n endLine: member.loc.end.line,\r\n content: sliceLines(content, member.loc.start.line, member.loc.end.line),\r\n tokens: 0,\r\n kind: getKind(member),\r\n name: getName(member as t.Node),\r\n };\r\n methodChunk.tokens = countTokens(methodChunk.content);\r\n chunks.push(methodChunk);\r\n }\r\n }\r\n }\r\n\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: loc.start.line,\r\n endLine: loc.end.line,\r\n content: sliceLines(content, loc.start.line, loc.end.line),\r\n tokens: 0,\r\n kind: getKind(node),\r\n name: getName(node),\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n visitedRanges.push([loc.start.line, loc.end.line]);\r\n }\r\n },\r\n });\r\n\r\n return mergeGaps(content, relPath, chunks, visitedRanges);\r\n}\r\n\r\n/**\r\n * Gap-filling between named chunks lives in merge-gaps.ts — it is shared\r\n * by the Babel and tree-sitter extraction paths.\r\n */\r\n\r\nfunction extractWithRegex(relPath: string, content: string): CodeChunk[] {\r\n const lines = content.split('\\n');\r\n const chunks: CodeChunk[] = [];\r\n let currentStart = 1;\r\n let currentLines: string[] = [];\r\n\r\n // Simple heuristic: split on blank lines or lines starting with `function`, `class`, `const`, etc.\r\n const re = /^(export\\s+)?(?:async\\s+)?(?:function\\s+\\w+|class\\s+\\w+|const\\s+\\w+|let\\s+\\w+|var\\s+\\w+|interface\\s+\\w+|type\\s+\\w+|def\\s+\\w+|struct\\s+\\w+|fn\\s+\\w+)/;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line.match(re) && currentLines.length > 0) {\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: currentStart,\r\n endLine: i,\r\n content: currentLines.join('\\n'),\r\n tokens: 0,\r\n kind: 'unknown',\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n currentStart = i + 1;\r\n currentLines = [line];\r\n } else {\r\n currentLines.push(line);\r\n }\r\n }\r\n\r\n if (currentLines.length) {\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: currentStart,\r\n endLine: lines.length,\r\n content: currentLines.join('\\n'),\r\n tokens: 0,\r\n kind: 'unknown',\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n }\r\n\r\n return chunks.filter(c => c.content.trim());\r\n}\r\n\r\n/**\r\n * Extract semantically meaningful chunks from a source file.\r\n * Uses Babel for JS/TS, tree-sitter for Python/Go/Rust/Java/C#/PHP\r\n * (when grammars are loaded via `ensureTreeSitterForExt`), and a\r\n * regex fallback for everything else.\r\n */\r\nexport function extractChunks(relPath: string, content: string): CodeChunk[] {\r\n const ext = relPath.slice(relPath.lastIndexOf('.')).toLowerCase();\r\n if (JS_LIKE.has(ext)) {\r\n try {\r\n return extractTopLevelWithBabel(relPath, content);\r\n } catch {\r\n // Fall back to regex if Babel fails (e.g. malformed code)\r\n return extractWithRegex(relPath, content);\r\n }\r\n }\r\n if (treeSitterReady(ext)) {\r\n try {\r\n const chunks = extractWithTreeSitter(ext, relPath, content);\r\n if (chunks && chunks.length) return chunks;\r\n } catch {\r\n // fall through to regex\r\n }\r\n }\r\n return extractWithRegex(relPath, content);\r\n}\r\n","import type { CodeChunk } from './types.js';\nimport { countTokens } from './tokenizer.js';\n\n/**\n * Add 'file' chunks covering lines not already in a named chunk,\n * so nothing is lost from the original file.\n */\nexport function mergeGaps(content: string, relPath: string, namedChunks: CodeChunk[], visitedRanges: [number, number][]): CodeChunk[] {\n const lines = content.split('\\n');\n if (lines.length === 0) return namedChunks;\n\n const covered = new Set<number>();\n for (const [start, end] of visitedRanges) {\n for (let i = start; i <= end; i++) covered.add(i);\n }\n\n const all: CodeChunk[] = [];\n let start = 1;\n for (let i = 1; i <= lines.length; i++) {\n if (!covered.has(i)) continue;\n if (i > start) {\n const gapText = lines.slice(start - 1, i - 1).join('\\n');\n if (gapText.trim()) all.push({ relPath, startLine: start, endLine: i - 1, content: gapText, tokens: countTokens(gapText), kind: 'file' });\n }\n start = i + 1;\n }\n if (start <= lines.length) {\n const gapText = lines.slice(start - 1).join('\\n');\n if (gapText.trim()) all.push({ relPath, startLine: start, endLine: lines.length, content: gapText, tokens: countTokens(gapText), kind: 'file' });\n }\n\n return [...all, ...namedChunks].sort((a, b) => a.startLine - b.startLine);\n}\n","import { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport type Parser from 'web-tree-sitter';\nimport type { CodeChunk } from './types.js';\nimport { countTokens } from './tokenizer.js';\nimport { mergeGaps } from './merge-gaps.js';\n\nconst require = createRequire(import.meta.url);\n\n/** File extension → tree-sitter-wasms grammar name. */\nconst GRAMMAR_BY_EXT: Record<string, string> = {\n '.py': 'python',\n '.go': 'go',\n '.rs': 'rust',\n '.java': 'java',\n '.cs': 'c_sharp',\n '.php': 'php',\n};\n\n/** node type → chunk kind, per grammar. */\nconst DECL_TYPES: Record<string, Record<string, CodeChunk['kind']>> = {\n python: {\n function_definition: 'function',\n class_definition: 'class',\n },\n go: {\n function_declaration: 'function',\n method_declaration: 'method',\n type_declaration: 'type',\n import_declaration: 'import',\n const_declaration: 'unknown',\n var_declaration: 'unknown',\n },\n rust: {\n function_item: 'function',\n struct_item: 'type',\n enum_item: 'type',\n union_item: 'type',\n trait_item: 'type',\n type_item: 'type',\n impl_item: 'type',\n mod_item: 'unknown',\n use_declaration: 'import',\n macro_definition: 'unknown',\n },\n java: {\n class_declaration: 'class',\n interface_declaration: 'type',\n enum_declaration: 'type',\n record_declaration: 'type',\n annotation_type_declaration: 'type',\n method_declaration: 'method',\n constructor_declaration: 'method',\n field_declaration: 'unknown',\n import_declaration: 'import',\n package_declaration: 'import',\n },\n c_sharp: {\n class_declaration: 'class',\n interface_declaration: 'type',\n struct_declaration: 'type',\n enum_declaration: 'type',\n record_declaration: 'type',\n delegate_declaration: 'type',\n method_declaration: 'method',\n constructor_declaration: 'method',\n property_declaration: 'method',\n field_declaration: 'unknown',\n using_directive: 'import',\n },\n php: {\n function_definition: 'function',\n class_declaration: 'class',\n interface_declaration: 'type',\n trait_declaration: 'type',\n enum_declaration: 'type',\n method_declaration: 'method',\n namespace_use_declaration: 'import',\n namespace_definition: 'unknown',\n },\n};\n\n/** Node types whose named children may contain more declarations. */\nconst RECURSE_INTO = new Set([\n 'program', 'module', 'translation_unit', 'compilation_unit', 'source_file',\n 'namespace_declaration', 'file_scoped_namespace_declaration', 'namespace_definition',\n 'declaration_list', 'decorated_definition', 'export_statement',\n]);\n\n/** Node types that act as member containers (methods/functions inside). */\nconst CONTAINER_TYPES = new Set([\n 'class_definition', 'class_declaration', 'interface_declaration',\n 'enum_declaration', 'record_declaration', 'struct_declaration',\n 'impl_item', 'trait_item', 'trait_declaration',\n]);\n\n/** Member node types emitted as 'method' chunks inside containers. */\nconst MEMBER_TYPES = new Set([\n 'function_definition', 'method_declaration', 'method_definition',\n 'function_item', 'constructor_declaration', 'property_declaration',\n]);\n\n/** Identifier-ish node types used as a name fallback. */\nconst NAME_TYPES = new Set([\n 'identifier', 'type_identifier', 'field_identifier', 'simple_type', 'name',\n]);\n\ntype TreeSitterModule = typeof Parser & { default?: typeof Parser };\n\nlet parser: Parser | null = null;\nlet initPromise: Promise<boolean> | null = null;\nconst languages = new Map<string, Parser.Language | null>();\nconst langPromises = new Map<string, Promise<Parser.Language | null>>();\n\n/** Initialize the WASM runtime once. Returns false when unavailable. */\nexport async function initTreeSitter(): Promise<boolean> {\n if (parser) return true;\n initPromise ??= (async () => {\n try {\n const mod = (await import('web-tree-sitter')) as unknown as TreeSitterModule;\n const ParserClass = mod.default ?? mod;\n // The .wasm lives next to the installed package, not next to dist/.\n const wasm = require.resolve('web-tree-sitter/tree-sitter.wasm');\n await ParserClass.init({ locateFile: () => wasm });\n parser = new ParserClass();\n return true;\n } catch {\n return false;\n }\n })();\n return initPromise;\n}\n\nfunction grammarPath(name: string): string {\n const pkg = require.resolve('tree-sitter-wasms/package.json');\n return join(dirname(pkg), 'out', `tree-sitter-${name}.wasm`);\n}\n\nasync function ensureLanguage(name: string): Promise<Parser.Language | null> {\n if (languages.has(name)) return languages.get(name)!;\n let p = langPromises.get(name);\n if (!p) {\n p = (async () => {\n try {\n const mod = (await import('web-tree-sitter')) as unknown as TreeSitterModule;\n const ParserClass = mod.default ?? mod;\n const lang = await ParserClass.Language.load(grammarPath(name));\n languages.set(name, lang);\n return lang;\n } catch {\n languages.set(name, null);\n return null;\n }\n })();\n langPromises.set(name, p);\n }\n return p;\n}\n\n/**\n * Make sure the grammar for `ext` is loaded (if the extension is supported).\n * Safe to call per file — repeated calls are cached.\n */\nexport async function ensureTreeSitterForExt(ext: string): Promise<boolean> {\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()];\n if (!name) return false;\n if (!(await initTreeSitter())) return false;\n return (await ensureLanguage(name)) != null;\n}\n\n/** Release the WASM parser — call before process exit to avoid libuv asserts. */\nexport function disposeTreeSitter(): void {\n try { parser?.delete(); } catch { /* best effort */ }\n parser = null;\n initPromise = null;\n languages.clear();\n langPromises.clear();\n}\n\n/** True when a grammar is loaded and ready for synchronous extraction. */\nexport function treeSitterReady(ext: string): boolean {\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()];\n return !!name && !!parser && languages.get(name) != null;\n}\n\nfunction nodeName(node: Parser.SyntaxNode): string | undefined {\n const named = node.childForFieldName('name');\n if (named) return named.text;\n for (const child of node.namedChildren) {\n if (NAME_TYPES.has(child.type)) return child.text;\n // Go: type_declaration → type_spec (name field)\n const inner = child.childForFieldName('name');\n if (inner) return inner.text;\n }\n return undefined;\n}\n\nfunction toChunk(node: Parser.SyntaxNode, kind: CodeChunk['kind'], relPath: string, content: string, name?: string): CodeChunk {\n const startLine = node.startPosition.row + 1;\n const endLine = node.endPosition.row + 1;\n const text = content.split('\\n').slice(startLine - 1, endLine).join('\\n');\n return { relPath, startLine, endLine, content: text, tokens: countTokens(text), kind, name };\n}\n\n/**\n * Extract declaration chunks with tree-sitter. Only call when\n * `treeSitterReady(ext)` is true; returns undefined on parse failure.\n */\nexport function extractWithTreeSitter(ext: string, relPath: string, content: string): CodeChunk[] | undefined {\n if (!parser || !treeSitterReady(ext)) return undefined;\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()]!;\n const lang = languages.get(name)!;\n const declTypes = DECL_TYPES[name] ?? {};\n\n let tree: Parser.Tree;\n try {\n parser.setLanguage(lang);\n tree = parser.parse(content);\n } catch {\n return undefined;\n }\n if (!tree) return undefined;\n\n try {\n const chunks: CodeChunk[] = [];\n const visitedRanges: [number, number][] = [];\n\n const handle = (child: Parser.SyntaxNode) => {\n const kind = declTypes[child.type];\n if (kind) {\n // Python decorators: widen the range to include decorator lines.\n const target = child.parent?.type === 'decorated_definition' ? child.parent : child;\n chunks.push(toChunk(target, kind, relPath, content, nodeName(child)));\n visitedRanges.push([target.startPosition.row + 1, target.endPosition.row + 1]);\n\n // Members of class-like containers become their own 'method' chunks.\n if (CONTAINER_TYPES.has(child.type)) {\n const body = child.childForFieldName('body') ?? child;\n for (const member of body.namedChildren) {\n if (MEMBER_TYPES.has(member.type)) {\n chunks.push(toChunk(member, 'method', relPath, content, nodeName(member)));\n } else if (declTypes[member.type]) {\n // Nested decls (e.g. enum inside class) — keep them too.\n handle(member);\n }\n }\n }\n return;\n }\n if (RECURSE_INTO.has(child.type) || child.namedChildren.some((c) => declTypes[c.type] || RECURSE_INTO.has(c.type))) {\n visit(child);\n }\n };\n\n const visit = (node: Parser.SyntaxNode) => {\n for (const child of node.namedChildren) handle(child);\n };\n visit(tree.rootNode);\n\n return mergeGaps(content, relPath, chunks, visitedRanges);\n } finally {\n tree.delete();\n }\n}\n\n\n","import { pipeline, type FeatureExtractionPipeline } from '@xenova/transformers';\r\nimport { chunkByTokens, countTokens } from './tokenizer.js';\r\n\r\nconst DEFAULT_MODEL = 'Xenova/paraphrase-multilingual-MiniLM-L12-v2';\r\n\r\nlet extractor: FeatureExtractionPipeline | null = null;\r\nlet activeModel = '';\r\n\r\nexport async function getExtractor(model = DEFAULT_MODEL): Promise<FeatureExtractionPipeline> {\r\n if (extractor && activeModel === model) return extractor;\r\n activeModel = model;\r\n extractor = await pipeline('feature-extraction', model, {\r\n quantized: true,\r\n });\r\n return extractor;\r\n}\r\n\r\n/** Truncate long texts to a token budget before embedding. */\r\nfunction prepareText(text: string, maxTokens = 256): string {\r\n if (countTokens(text) <= maxTokens) return text;\r\n return chunkByTokens(text, maxTokens)[0] ?? text.slice(0, 1024);\r\n}\r\n\r\nfunction tensorToVectors(tensor: { dims: number[]; data: Float32Array }): number[][] {\r\n const [count, dim] = tensor.dims;\r\n const vectors: number[][] = [];\r\n for (let i = 0; i < count; i++) {\r\n vectors.push(Array.from(tensor.data.subarray(i * dim, (i + 1) * dim)));\r\n }\r\n return vectors;\r\n}\r\n\r\n/** Compute a single embedding. */\r\nexport async function getEmbedding(text: string, model = DEFAULT_MODEL): Promise<number[]> {\r\n const pipe = await getExtractor(model);\r\n const out = (await pipe(prepareText(text), {\r\n pooling: 'mean',\r\n normalize: true,\r\n })) as unknown as { data: Float32Array };\r\n return Array.from(out.data);\r\n}\r\n\r\n/** Compute embeddings for many texts in one call. */\r\nexport async function getEmbeddings(texts: string[], model = DEFAULT_MODEL): Promise<number[][]> {\r\n const pipe = await getExtractor(model);\r\n const inputs = texts.map(t => prepareText(t));\r\n const out = (await pipe(inputs, {\r\n pooling: 'mean',\r\n normalize: true,\r\n })) as unknown as { dims: number[]; data: Float32Array };\r\n return tensorToVectors(out);\r\n}\r\n\r\n/** Cosine similarity of two normalized vectors (or any vectors). */\r\nexport function cosineSimilarity(a: number[], b: number[]): number {\r\n let dot = 0;\r\n for (let i = 0; i < a.length; i++) {\r\n dot += a[i] * b[i];\r\n }\r\n return dot;\r\n}\r\n","import { readdir, readFile, stat } from 'node:fs/promises';\r\nimport { extname, join, relative, resolve, sep, isAbsolute } from 'node:path';\r\nimport { createHash } from 'node:crypto';\r\nimport { homedir } from 'node:os';\r\nimport { loadProjectConfig, matchesAnyGlob, type ProjectConfig } from './config.js';\r\n\r\nexport interface TreeOptions {\r\n maxLines?: number;\r\n skipDirs?: Set<string>;\r\n}\r\n\r\nconst SOURCE_EXTS = new Set([\r\n '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',\r\n '.vue', '.svelte', '.py', '.rs', '.go', '.java', '.kt',\r\n '.swift', '.cs', '.cpp', '.c', '.h', '.hpp',\r\n '.css', '.scss', '.less', '.html', '.json', '.yaml', '.yml', '.md'\r\n]);\r\n\r\nconst DEFAULT_SKIP_DIRS = new Set([\r\n 'node_modules', '.git', 'dist', 'build', 'out', '.output',\r\n 'coverage', 'tmp', 'temp', '.cache', '.turbo', '.next',\r\n 'android', 'ios', 'e2e-shots', 'playstore_screenshots',\r\n '.cursor', '.idea', '.memsearch', '.vscode', '__pycache__',\r\n '.dsh-tmp', '.dsh-vision-router'\r\n]);\r\n\r\nconst DEFAULT_SKIP_FILES = new Set<string>([]);\r\n\r\nexport interface WalkOptions {\r\n skipDirs?: Set<string>;\r\n skipFiles?: Set<string>;\r\n ignoreGlobs?: string[];\r\n}\r\n\r\n/** Merge built-in skip lists with the project's `.codebase-chat.json` settings. */\r\nexport async function getWalkOptions(absProject: string): Promise<Required<WalkOptions>> {\r\n const cfg: ProjectConfig = await loadProjectConfig(absProject);\r\n return {\r\n skipDirs: new Set([...DEFAULT_SKIP_DIRS, ...(cfg.ignoreDirs ?? [])]),\r\n skipFiles: new Set([...DEFAULT_SKIP_FILES, ...(cfg.ignoreFiles ?? [])]),\r\n ignoreGlobs: cfg.ignoreGlobs ?? [],\r\n };\r\n}\r\n\r\nexport function projectHash(absProject: string): string {\r\n return createHash('sha256').update(absProject.toLowerCase()).digest('hex').slice(0, 16);\r\n}\r\n\r\nexport function resolveProjectPath(projectPath?: string): string {\r\n const raw = (projectPath ?? '').trim().toLowerCase().replace(/['\"]/g, '');\r\n if (raw === 'dako') return 'D:\\\\Nouveau dossier';\r\n if (!projectPath) return process.cwd();\r\n if (isAbsolute(projectPath)) return resolve(projectPath);\r\n return resolve(process.cwd(), projectPath);\r\n}\r\n\r\nexport async function findProjectRoot(absProject: string): Promise<string> {\r\n try {\r\n const s = await stat(absProject);\r\n if (s.isDirectory()) return absProject;\r\n // If user points to a file, use its directory\r\n return resolve(absProject, '..');\r\n } catch {\r\n throw new Error(`Project path not found: ${absProject}`);\r\n }\r\n}\r\n\r\nexport function getCacheDir(): string {\r\n const base = process.env.CODEBASE_CACHE_DIR\r\n || process.env.LOCALAPPDATA\r\n || process.env.APPDATA\r\n || join(homedir(), '.cache');\r\n return join(base, 'dsh-codebase-chat-cache');\r\n}\r\n\r\nexport function cacheFilePath(absProject: string): string {\r\n return join(getCacheDir(), `${projectHash(absProject)}.json`);\r\n}\r\n\r\nexport function fileHash(stats: { mtimeMs: number; size: number }, firstBytes = ''): string {\r\n return createHash('sha256')\r\n .update(`${stats.mtimeMs}:${stats.size}:${firstBytes.slice(0, 512)}`)\r\n .digest('hex')\r\n .slice(0, 24);\r\n}\r\n\r\nexport async function* walkFiles(startDir: string, skipDirs = DEFAULT_SKIP_DIRS, skipFiles = DEFAULT_SKIP_FILES, ignoreGlobs: string[] = []): AsyncGenerator<string> {\r\n const queue: string[] = [startDir];\r\n while (queue.length) {\r\n const dir = queue.shift()!;\r\n let entries;\r\n try {\r\n entries = await readdir(dir, { withFileTypes: true });\r\n } catch {\r\n continue;\r\n }\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n const rel = relative(startDir, fullPath).split(sep).join('/');\r\n if (entry.isDirectory()) {\r\n if (!skipDirs.has(entry.name) && !matchesAnyGlob(rel, ignoreGlobs)) queue.push(fullPath);\r\n continue;\r\n }\r\n if (!entry.isFile()) continue;\r\n if (skipFiles.has(entry.name)) continue;\r\n if (matchesAnyGlob(rel, ignoreGlobs)) continue;\r\n const ext = extname(entry.name).toLowerCase();\r\n if (!SOURCE_EXTS.has(ext)) continue;\r\n yield fullPath;\r\n }\r\n }\r\n}\r\n\r\nexport async function safeReadText(filePath: string): Promise<string | undefined> {\r\n try {\r\n const text = await readFile(filePath, 'utf8');\r\n return text;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport async function buildTree(startDir: string, maxLines = 500, skipDirs = DEFAULT_SKIP_DIRS): Promise<string> {\r\n const lines: string[] = [];\r\n\r\n async function walk(dir: string, prefix = '') {\r\n if (lines.length >= maxLines) return;\r\n let entries;\r\n try {\r\n entries = await readdir(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n entries.sort((a, b) => (a.isDirectory() === b.isDirectory() ? a.name.localeCompare(b.name) : a.isDirectory() ? -1 : 1));\r\n for (const entry of entries) {\r\n if (lines.length >= maxLines) return;\r\n if (skipDirs.has(entry.name)) continue;\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n lines.push(`${prefix}${entry.name}/`);\r\n await walk(fullPath, `${prefix} `);\r\n } else {\r\n lines.push(`${prefix}${entry.name}`);\r\n }\r\n }\r\n }\r\n\r\n await walk(startDir);\r\n return lines.join('\\n');\r\n}\r\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type ConfigLang = 'fr' | 'en';\n\n/**\n * Per-project settings read from `.codebase-chat.json` at the project root.\n * Every field is optional — unset fields fall back to built-in defaults.\n */\nexport interface ProjectConfig {\n /** Default output language when the caller does not pass `lang` */\n lang?: ConfigLang;\n /** Default token budget for built contexts when the caller does not pass `maxTokens` */\n maxTokens?: number;\n /** Extra directory names skipped during indexing and analysis */\n ignoreDirs?: string[];\n /** Extra file names skipped during indexing and analysis */\n ignoreFiles?: string[];\n /** Glob patterns matched against project-relative paths (e.g. \"generated/**\") */\n ignoreGlobs?: string[];\n /** Extra paths that can never be patched (project-relative or absolute) */\n protectedPaths?: string[];\n}\n\nexport const CONFIG_FILE = '.codebase-chat.json';\n\nconst configCache = new Map<string, ProjectConfig>();\n\nfunction strArray(v: unknown): string[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out = v.filter((x): x is string => typeof x === 'string' && x.trim().length > 0);\n return out.length ? out.map(s => s.trim()) : undefined;\n}\n\nfunction sanitize(raw: unknown): ProjectConfig {\n if (raw == null || typeof raw !== 'object') return {};\n const o = raw as Record<string, unknown>;\n const cfg: ProjectConfig = {};\n if (o.lang === 'fr' || o.lang === 'en') cfg.lang = o.lang;\n if (typeof o.maxTokens === 'number' && Number.isFinite(o.maxTokens) && o.maxTokens > 0) {\n cfg.maxTokens = Math.floor(o.maxTokens);\n }\n const ignoreDirs = strArray(o.ignoreDirs); if (ignoreDirs) cfg.ignoreDirs = ignoreDirs;\n const ignoreFiles = strArray(o.ignoreFiles); if (ignoreFiles) cfg.ignoreFiles = ignoreFiles;\n const ignoreGlobs = strArray(o.ignoreGlobs); if (ignoreGlobs) cfg.ignoreGlobs = ignoreGlobs;\n const protectedPaths = strArray(o.protectedPaths); if (protectedPaths) cfg.protectedPaths = protectedPaths;\n return cfg;\n}\n\n/** Read `.codebase-chat.json` from the project root. Missing/invalid file → defaults. */\nexport async function loadProjectConfig(absProject: string): Promise<ProjectConfig> {\n const cached = configCache.get(absProject);\n if (cached) return cached;\n let cfg: ProjectConfig = {};\n try {\n cfg = sanitize(JSON.parse(await readFile(join(absProject, CONFIG_FILE), 'utf8')));\n } catch {\n // missing or malformed config file — keep defaults\n }\n configCache.set(absProject, cfg);\n return cfg;\n}\n\n/** Test/debug helper: drop the cached config for a project. */\nexport function clearConfigCache(absProject?: string): void {\n if (absProject == null) configCache.clear();\n else configCache.delete(absProject);\n}\n\nfunction escapeSegment(s: string): string {\n return s.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*').replace(/\\?/g, '[^/]');\n}\n\n/** Minimal glob → RegExp: `**` spans directories, `*` one segment, `?` one char. */\nexport function globToRegExp(glob: string): RegExp {\n const src = glob.replace(/\\\\/g, '/').split('**').map(escapeSegment).join('.*');\n return new RegExp(`^${src}$`);\n}\n\n/** Match a project-relative path (posix separators) against a list of globs. */\nexport function matchesAnyGlob(relPath: string, globs: string[] | undefined): boolean {\n if (!globs || globs.length === 0) return false;\n const rel = relPath.replace(/\\\\/g, '/');\n return globs.some(g => globToRegExp(g).test(rel));\n}\n","import type { CodeChunk, CodeIndex } from './types.js';\r\nimport { getEmbedding, cosineSimilarity } from './embeddings.js';\r\n\r\nconst STOP_WORDS = new Set([\r\n 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought', 'used', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'and', 'or', 'but', 'so', 'yet', 'a', 'an', 'this', 'that', 'these', 'those', 'it', 'its', 'he', 'she', 'they', 'them', 'their', 'we', 'us', 'our', 'you', 'your', 'i', 'me', 'my', 'le', 'la', 'les', 'un', 'une', 'des', 'du', 'de', 'et', 'ou', 'que', 'qui', 'quoi', 'dont', 'ce', 'cet', 'cette', 'ces', 'est', 'sont', 'etait', 'etaient', 'avoir', 'etre', 'faire', 'dans', 'pour', 'sur', 'avec', 'par', 'a', 'au', 'aux'\r\n]);\r\n\r\nfunction tokenizeQuery(text: string): string[] {\r\n return text\r\n .replace(/[^a-zA-Z0-9\\u00C0-\\u017F]+/g, ' ')\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter(Boolean)\r\n .filter(t => t.length > 2 && !STOP_WORDS.has(t));\r\n}\r\n\r\ninterface ScoredChunk extends CodeChunk {\r\n score: number;\r\n}\r\n\r\nfunction getChunkKey(chunk: CodeChunk): string {\r\n return `${chunk.relPath}:${chunk.startLine}:${chunk.endLine}`;\r\n}\r\n\r\nfunction lexicalScore(index: CodeIndex, query: string): Map<string, number> {\r\n const terms = tokenizeQuery(query);\r\n const scores = new Map<string, number>();\r\n\r\n if (terms.length === 0) return scores;\r\n\r\n for (const term of terms) {\r\n const posting = index.terms[term];\r\n if (!posting) continue;\r\n for (const [relPath, count] of Object.entries(posting)) {\r\n const file = index.files[relPath];\r\n if (!file) continue;\r\n for (const chunk of file.chunks) {\r\n const key = getChunkKey(chunk);\r\n const contentHit = chunk.content.toLowerCase().includes(term);\r\n const nameHit = chunk.name ? tokenizeQuery(chunk.name).includes(term) : false;\r\n // File-level term counts only matter for chunks that actually mention\r\n // the term — otherwise every chunk in a matched file inherits the score.\r\n if (!contentHit && !nameHit) continue;\r\n const bonus =\r\n (nameHit ? 4 : 0) +\r\n (chunk.kind === 'function' || chunk.kind === 'method' ? 1 : 0) +\r\n (contentHit ? 1 : 0);\r\n const prev = scores.get(key) ?? 0;\r\n scores.set(key, prev + count + bonus);\r\n }\r\n }\r\n }\r\n\r\n return scores;\r\n}\r\n\r\n/**\r\n * Score all chunks against a query using the inverted index and, when available,\r\n * local sentence embeddings.\r\n */\r\nexport async function scoreChunks(index: CodeIndex, query: string, embed = false): Promise<ScoredChunk[]> {\r\n const lexScores = lexicalScore(index, query);\r\n\r\n // gather all chunks once\r\n const allChunks: CodeChunk[] = [];\r\n for (const file of Object.values(index.files)) {\r\n allChunks.push(...file.chunks);\r\n }\r\n\r\n let queryEmbedding: number[] | null = null;\r\n const hasEmbeddings = embed && allChunks.some(c => c.embedding && c.embedding.length > 0);\r\n\r\n if (hasEmbeddings) {\r\n try {\r\n queryEmbedding = await getEmbedding(query);\r\n } catch {\r\n queryEmbedding = null;\r\n }\r\n }\r\n\r\n const scored: ScoredChunk[] = [];\r\n for (const chunk of allChunks) {\r\n const key = getChunkKey(chunk);\r\n let score = lexScores.get(key) ?? 0;\r\n\r\n if (queryEmbedding && chunk.embedding && chunk.embedding.length === queryEmbedding.length) {\r\n const sim = cosineSimilarity(queryEmbedding, chunk.embedding);\r\n // semantic score is in [0, 1], scale it so it competes with lexical scores\r\n score += sim * 50;\r\n } else if (score === 0 && !hasEmbeddings) {\r\n // when no query terms matched and no embeddings, still return a fallback\r\n score = 0.1;\r\n }\r\n\r\n scored.push({ ...chunk, score });\r\n }\r\n\r\n return scored.sort((a, b) => b.score - a.score);\r\n}\r\n\r\n/**\r\n * Select chunks to fit within a token budget, keeping the most relevant first.\r\n */\r\nexport function selectChunks(scored: ScoredChunk[], maxTokens: number, maxChunkTokens = Infinity): { chunks: CodeChunk[]; tokens: number } {\r\n const result: CodeChunk[] = [];\r\n const covered = new Map<string, [number, number][]>();\r\n let used = 0;\r\n for (const chunk of scored) {\r\n if (chunk.tokens > maxChunkTokens) continue;\r\n if (used + chunk.tokens > maxTokens) continue;\r\n // Skip chunks fully covered by an already-selected chunk of the same file\r\n // (e.g. a method chunk inside a class chunk already picked).\r\n const ranges = covered.get(chunk.relPath) ?? [];\r\n const duplicated = ranges.some(([s, e]) => chunk.startLine >= s && chunk.endLine <= e);\r\n if (duplicated) continue;\r\n ranges.push([chunk.startLine, chunk.endLine]);\r\n covered.set(chunk.relPath, ranges);\r\n result.push(chunk);\r\n used += chunk.tokens;\r\n }\r\n return { chunks: result, tokens: used };\r\n}\r\n","import { basename, extname, join, relative, sep, posix as posixPath } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { findProjectRoot, getWalkOptions, resolveProjectPath, safeReadText, walkFiles } from './project.js';\n\nconst CODE_EXTS = new Set(['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx']);\nconst ENTRY_BASENAMES = new Set(['index', 'main', 'app', 'cli', 'server', 'bin', 'mod']);\nconst SKIP_EXTS = new Set(['.d.ts', '.test.ts', '.test.js', '.spec.ts', '.spec.js', '.config.js', '.config.ts', '.config.mjs']);\n\nexport interface ImportEdge { from: string; to: string; }\nexport interface Cycle { path: string[]; }\nexport interface UnusedExport { file: string; name: string; line: number; }\nexport interface CloneGroup { files: string[]; lines: number; preview: string; }\nexport interface Hotspot { file: string; name?: string; startLine: number; score: number; }\n\nexport interface HealthReport {\n projectPath: string;\n analyzedFiles: number;\n importEdges: number;\n cycles: Cycle[];\n unusedFiles: string[];\n unusedExports: UnusedExport[];\n duplicates: CloneGroup[];\n hotspots: Hotspot[];\n score: number;\n grade: 'A' | 'B' | 'C' | 'D' | 'E';\n}\n\nconst IMPORT_RE = /(?:import|export)\\s+(?:[\\w*{}\\s,]+\\s+from\\s+)?['\"]([^'\"]+)['\"]|require\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)|import\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\nconst EXPORT_RE = /export\\s+(?:async\\s+)?(?:function|class|const|let|var|interface|type|enum)\\s+([A-Za-z_$][\\w$]*)|export\\s*\\{\\s*([^}]+)\\}|export\\s+default\\b/g;\n\nfunction parseImports(text: string, relPath: string, known: Set<string>): string[] {\n const out: string[] = [];\n let m: RegExpExecArray | null;\n IMPORT_RE.lastIndex = 0;\n while ((m = IMPORT_RE.exec(text)) !== null) {\n const spec = m[1] ?? m[2] ?? m[3];\n if (!spec || !spec.startsWith('.')) continue;\n const base = posixPath.normalize(posixPath.join(posixPath.dirname(relPath), spec));\n // ESM imports often use a .js extension pointing at a .ts source file.\n const noExt = base.replace(/\\.(js|jsx|mjs|cjs|ts|tsx)$/, '');\n for (const cand of [base, `${noExt}.ts`, `${noExt}.tsx`, `${noExt}.js`, `${noExt}.jsx`, `${noExt}.mjs`, `${base}/index.ts`, `${base}/index.js`]) {\n if (known.has(cand)) { out.push(cand); break; }\n }\n }\n return out;\n}\n\nfunction parseExports(text: string): { name: string; line: number }[] {\n const out: { name: string; line: number }[] = [];\n let m: RegExpExecArray | null;\n EXPORT_RE.lastIndex = 0;\n while ((m = EXPORT_RE.exec(text)) !== null) {\n const line = text.slice(0, m.index).split('\\n').length;\n if (m[1]) out.push({ name: m[1], line });\n else if (m[2]) {\n for (const part of m[2].split(',')) {\n const name = part.trim().split(/\\s+as\\s+/).pop()?.trim();\n if (name) out.push({ name, line });\n }\n } else out.push({ name: 'default', line });\n }\n return out;\n}\n\n/** Detect cycles in the local import graph (DFS, deduplicated up to rotation). */\nfunction findCycles(edges: ImportEdge[]): Cycle[] {\n const adj = new Map<string, string[]>();\n for (const e of edges) {\n if (!adj.has(e.from)) adj.set(e.from, []);\n adj.get(e.from)!.push(e.to);\n }\n const cycles: Cycle[] = [];\n const seen = new Set<string>();\n const stack: string[] = [];\n const onStack = new Set<string>();\n\n function dfs(node: string) {\n stack.push(node);\n onStack.add(node);\n for (const next of adj.get(node) ?? []) {\n if (onStack.has(next)) {\n const cycle = stack.slice(stack.indexOf(next)).concat(next);\n // canonical rotation for dedupe\n const body = cycle.slice(0, -1);\n const minIdx = body.indexOf(body.reduce((a, b) => (a < b ? a : b)));\n const key = body.slice(minIdx).concat(body.slice(0, minIdx)).join('>');\n if (!seen.has(key)) {\n seen.add(key);\n cycles.push({ path: cycle });\n }\n } else if (!stack.includes(next)) {\n dfs(next);\n }\n }\n stack.pop();\n onStack.delete(node);\n }\n\n for (const n of adj.keys()) dfs(n);\n return cycles;\n}\n\nfunction looksLikeEntry(rel: string, pkg: Record<string, any>): boolean {\n const base = basename(rel).toLowerCase().replace(extname(rel), '');\n if (ENTRY_BASENAMES.has(base)) return true;\n // Test/spec files and tool configs are entry points by convention —\n // they are executed, not imported.\n if (/\\.(test|spec)\\.[cm]?[jt]sx?$/.test(rel) || rel.includes('__tests__/') || /^e2e[.-]/.test(basename(rel))) return true;\n if (/\\.(config|rc)\\.[cm]?[jt]s$/.test(rel)) return true;\n if (/^(pages|app|routes|api|bin|scripts)\\//.test(rel) || rel.includes('/pages/') || rel.includes('/routes/')) return true;\n const fields = [pkg?.main, pkg?.module, pkg?.bin, pkg?.exports?.['.']];\n for (const f of fields.flatMap(v => (typeof v === 'string' ? [v] : v ? Object.values(v) : []))) {\n if (typeof f === 'string' && rel.endsWith(f.replace(/^\\.\\//, ''))) return true;\n }\n return false;\n}\n\nfunction complexityOf(text: string): number {\n const matches = text.match(/\\b(if|else if|for|while|case|catch|&&|\\|\\||\\?)\\b|\\?\\./g);\n return 1 + (matches ? matches.length : 0);\n}\n\nconst WINDOW = 6;\nfunction findDuplicates(fileTexts: Map<string, string>): CloneGroup[] {\n const windows = new Map<string, { file: string; line: number }[]>();\n for (const [file, text] of fileTexts) {\n const lines = text.split('\\n').map(l => l.trim()).filter(l => l && !l.startsWith('//') && l !== '{' && l !== '}');\n for (let i = 0; i + WINDOW <= lines.length; i++) {\n const key = lines.slice(i, i + WINDOW).join('\\n');\n if (key.length < 60) continue;\n if (!windows.has(key)) windows.set(key, []);\n const arr = windows.get(key)!;\n if (!arr.some(w => w.file === file)) arr.push({ file, line: i + 1 });\n }\n }\n const groups = new Map<string, CloneGroup>();\n for (const [key, hits] of windows) {\n if (hits.length < 2) continue;\n const files = [...new Set(hits.map(h => h.file))].sort();\n const gk = files.join('|');\n const preview = key.split('\\n')[0].slice(0, 80);\n const g = groups.get(gk);\n if (g) g.lines += WINDOW;\n else groups.set(gk, { files, lines: WINDOW, preview });\n }\n return [...groups.values()].sort((a, b) => b.lines - a.lines).slice(0, 15);\n}\n\nexport async function analyzeProject(projectPath: string): Promise<HealthReport> {\n const abs = await findProjectRoot(resolveProjectPath(projectPath));\n const fileTexts = new Map<string, string>();\n const codeFiles: string[] = [];\n const walk = await getWalkOptions(abs);\n\n for await (const full of walkFiles(abs, walk.skipDirs, walk.skipFiles, walk.ignoreGlobs)) {\n const rel = relative(abs, full).split(sep).join('/');\n const ext = extname(rel).toLowerCase();\n if (!CODE_EXTS.has(ext) || SKIP_EXTS.has(ext) || rel.includes('.min.')) continue;\n const text = await safeReadText(full);\n if (!text) continue;\n codeFiles.push(rel);\n fileTexts.set(rel, text);\n }\n\n let pkg: Record<string, any> = {};\n try { pkg = JSON.parse(await readFile(join(abs, 'package.json'), 'utf8')); } catch {}\n\n const known = new Set(codeFiles);\n const edges: ImportEdge[] = [];\n const inDegree = new Map<string, number>();\n for (const rel of codeFiles) {\n for (const to of parseImports(fileTexts.get(rel)!, rel, known)) {\n edges.push({ from: rel, to });\n inDegree.set(to, (inDegree.get(to) ?? 0) + 1);\n }\n }\n\n const cycles = findCycles(edges);\n\n const unusedFiles = codeFiles\n .filter(rel => !inDegree.has(rel) && !looksLikeEntry(rel, pkg))\n .sort();\n\n // Unused exports: name not imported and not referenced elsewhere.\n const otherText = new Map<string, string>();\n for (const [file, text] of fileTexts) otherText.set(file, text);\n const unusedExports: UnusedExport[] = [];\n for (const rel of codeFiles) {\n for (const exp of parseExports(fileTexts.get(rel)!)) {\n if (exp.name === 'default') continue;\n let used = false;\n for (const [otherFile, text] of fileTexts) {\n if (otherFile === rel) continue;\n if (new RegExp(`\\\\b${exp.name.replace(/[$_]/g, '\\\\$&')}\\\\b`).test(text)) { used = true; break; }\n }\n if (!used) unusedExports.push({ file: rel, name: exp.name, line: exp.line });\n }\n }\n\n const duplicates = findDuplicates(fileTexts);\n\n const hotspots: Hotspot[] = [];\n for (const [rel, text] of fileTexts) {\n const score = complexityOf(text);\n if (score >= 12) hotspots.push({ file: rel, startLine: 1, score });\n }\n hotspots.sort((a, b) => b.score - a.score);\n\n const codeLines = [...fileTexts.values()].reduce((s, t) => s + t.split('\\n').length, 0);\n const dupLines = duplicates.reduce((s, g) => s + g.lines, 0);\n const penalties =\n cycles.length * 6 +\n unusedFiles.length * 2 +\n Math.min(unusedExports.length, 20) * 1 +\n Math.round((dupLines / Math.max(codeLines, 1)) * 100) +\n Math.min(hotspots.length, 15) * 2;\n const score = Math.max(0, Math.min(100, 100 - penalties));\n const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 65 ? 'C' : score >= 50 ? 'D' : 'E';\n\n return {\n projectPath: abs,\n analyzedFiles: codeFiles.length,\n importEdges: edges.length,\n cycles,\n unusedFiles,\n unusedExports,\n duplicates,\n hotspots,\n score,\n grade,\n };\n}\n\nexport function formatHealthReport(r: HealthReport, lang: 'fr' | 'en' = 'fr'): string {\n const t = lang === 'en'\n ? {\n title: 'STATIC ANALYSIS', files: 'files analyzed', edges: 'local imports',\n cycles: 'Circular dependencies', none: 'none',\n unusedFiles: 'Unused files (candidates)', unusedExports: 'Unused exports (candidates)',\n dupes: 'Duplicate code blocks', hotspots: 'Complexity hotspots',\n score: 'Health score', noteUnused: 'candidates — entry points and framework conventions excluded',\n }\n : {\n title: 'ANALYSE STATIQUE', files: 'fichiers analysés', edges: 'imports locaux',\n cycles: 'Dépendances circulaires', none: 'aucune',\n unusedFiles: 'Fichiers inutilisés (candidats)', unusedExports: 'Exports inutilisés (candidats)',\n dupes: 'Blocs de code dupliqués', hotspots: 'Hotspots de complexité',\n score: 'Score de santé', noteUnused: 'candidats — points d’entrée et conventions exclus',\n };\n\n const out: string[] = [];\n out.push(`== ${t.title} — ${basename(r.projectPath)} ==`);\n out.push(`${t.score}: ${r.score}/100 (${r.grade}) · ${r.analyzedFiles} ${t.files} · ${r.importEdges} ${t.edges}`);\n out.push('');\n\n out.push(`● ${t.cycles} (${r.cycles.length})`);\n for (const c of r.cycles.slice(0, 10)) out.push(` ${c.path.join(' → ')}`);\n if (r.cycles.length === 0) out.push(` ${t.none}`);\n out.push('');\n\n out.push(`● ${t.unusedFiles} (${r.unusedFiles.length}) — ${t.noteUnused}`);\n for (const f of r.unusedFiles.slice(0, 15)) out.push(` ${f}`);\n out.push('');\n\n out.push(`● ${t.unusedExports} (${r.unusedExports.length})`);\n for (const e of r.unusedExports.slice(0, 15)) out.push(` ${e.file}:${e.line} — ${e.name}`);\n out.push('');\n\n out.push(`● ${t.dupes} (${r.duplicates.length})`);\n for (const d of r.duplicates.slice(0, 8)) out.push(` ${d.lines} lines × ${d.files.length} files — ${d.files.join(', ')}`);\n out.push('');\n\n out.push(`● ${t.hotspots} (${r.hotspots.length})`);\n for (const h of r.hotspots.slice(0, 10)) out.push(` ${h.file} — score ${h.score}`);\n return out.join('\\n');\n}\n\nconst GRADE_ICON: Record<HealthReport['grade'], string> = { A: '🟢', B: '🔵', C: '🟡', D: '🟠', E: '🔴' };\n\nfunction scoreBar(score: number): string {\n const filled = Math.round(score / 10);\n return '█'.repeat(filled) + '░'.repeat(10 - filled);\n}\n\nexport function formatHealthReportMd(r: HealthReport, lang: 'fr' | 'en' = 'fr'): string {\n const t = lang === 'en'\n ? {\n title: 'Static analysis', files: 'files analyzed', edges: 'local imports',\n cycles: 'Circular dependencies', none: 'None',\n unusedFiles: 'Unused files (candidates)', unusedExports: 'Unused exports (candidates)',\n dupes: 'Duplicate code blocks', hotspots: 'Complexity hotspots',\n score: 'Health score', noteUnused: '_candidates — entry points and framework conventions excluded_',\n colFile: 'File', colSymbol: 'Symbol', colSize: 'Size', colFiles: 'Files', colScore: 'Score',\n more: (n: number) => `_…and ${n} more_`,\n }\n : {\n title: 'Analyse statique', files: 'fichiers analysés', edges: 'imports locaux',\n cycles: 'Dépendances circulaires', none: 'Aucune',\n unusedFiles: 'Fichiers inutilisés (candidats)', unusedExports: 'Exports inutilisés (candidats)',\n dupes: 'Blocs de code dupliqués', hotspots: 'Hotspots de complexité',\n score: 'Score de santé', noteUnused: '_candidats — points d’entrée et conventions exclus_',\n colFile: 'Fichier', colSymbol: 'Symbole', colSize: 'Taille', colFiles: 'Fichiers', colScore: 'Score',\n more: (n: number) => `_…et ${n} autres_`,\n };\n\n const out: string[] = [];\n out.push(`## ${GRADE_ICON[r.grade]} ${t.title} — \\`${basename(r.projectPath)}\\``);\n out.push('');\n out.push(`**${t.score} : ${scoreBar(r.score)} ${r.score}/100 (${r.grade})** · ${r.analyzedFiles} ${t.files} · ${r.importEdges} ${t.edges}`);\n out.push('');\n\n out.push(`### ${t.cycles} — ${r.cycles.length}`);\n if (r.cycles.length === 0) out.push(t.none);\n else for (const c of r.cycles.slice(0, 10)) out.push(`- \\`${c.path.join('` → `')}\\``);\n if (r.cycles.length > 10) out.push(t.more(r.cycles.length - 10));\n out.push('');\n\n out.push(`### ${t.unusedFiles} — ${r.unusedFiles.length}`);\n out.push(t.noteUnused);\n if (r.unusedFiles.length) {\n out.push('', `| ${t.colFile} |`, '|---|---|');\n for (const f of r.unusedFiles.slice(0, 15)) out.push(`| \\`${f}\\` |`);\n if (r.unusedFiles.length > 15) out.push(`| ${t.more(r.unusedFiles.length - 15)} |`);\n }\n out.push('');\n\n out.push(`### ${t.unusedExports} — ${r.unusedExports.length}`);\n if (r.unusedExports.length) {\n out.push('', `| ${t.colFile} | ${t.colSymbol} |`, '|---|---|');\n for (const e of r.unusedExports.slice(0, 15)) out.push(`| \\`${e.file}:${e.line}\\` | \\`${e.name}\\` |`);\n if (r.unusedExports.length > 15) out.push(`| ${t.more(r.unusedExports.length - 15)} | |`);\n } else out.push(t.none);\n out.push('');\n\n out.push(`### ${t.dupes} — ${r.duplicates.length}`);\n if (r.duplicates.length) {\n out.push('', `| ${t.colSize} | ${t.colFiles} |`, '|---|---|');\n for (const d of r.duplicates.slice(0, 8)) {\n out.push(`| ${d.lines} × ${d.files.length} | ${d.files.map(f => `\\`${f}\\``).join(', ')} |`);\n }\n if (r.duplicates.length > 8) out.push(`| ${t.more(r.duplicates.length - 8)} | |`);\n } else out.push(t.none);\n out.push('');\n\n out.push(`### ${t.hotspots} — ${r.hotspots.length}`);\n if (r.hotspots.length) {\n out.push('', `| ${t.colFile} | ${t.colScore} |`, '|---|---|');\n for (const h of r.hotspots.slice(0, 10)) out.push(`| \\`${h.file}\\` | **${h.score}** |`);\n if (r.hotspots.length > 10) out.push(`| ${t.more(r.hotspots.length - 10)} | |`);\n } else out.push(t.none);\n\n return out.join('\\n');\n}\n"],"mappings":"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","names":["join","readFile","stat","dirname","join","relative","sep","start","require","t","readFile","join","join","join","readFile","t","readFile","dirname","sep","relative","stat","join","STOP_WORDS","t","join","extname","join","relative","sep","readFile","extname","relative","sep","readFile","join","score","t"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/context.ts","../src/tokenizer.ts","../src/indexer.ts","../src/extractor.ts","../src/merge-gaps.ts","../src/treesitter.ts","../src/embeddings.ts","../src/project.ts","../src/config.ts","../src/retriever.ts","../src/diff.ts","../src/analysis.ts","../src/impact.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\nimport { watch } from 'node:fs';\nimport { sep } from 'node:path';\nimport { buildContext } from './context.js';\nimport { getIndex } from './indexer.js';\nimport { findProjectRoot, getWalkOptions, resolveProjectPath } from './project.js';\nimport { analyzeProject, formatHealthReport } from './analysis.js';\nimport { analyzeImpact, formatImpactReport } from './impact.js';\nimport { getChangedFiles } from './diff.js';\nimport { loadProjectConfig } from './config.js';\nimport { disposeTreeSitter } from './treesitter.js';\n\nclass ExitSignal {\n constructor(public code: number) {}\n}\n\nfunction exit(code: number): never {\n disposeTreeSitter();\n // Natural exit preferred (avoids a libuv assert while Emscripten handles\n // close); the unref'd timer only forces it if the loop stays alive.\n setTimeout(() => process.exit(code), 2000).unref();\n throw new ExitSignal(code);\n}\n\nfunction printHelp() {\n console.log(`\ndsh-codebase-chat CLI\n\nUsage:\n npx dsh-codebase-chat --project <path> --ask \"Explain auth flow\"\n npx dsh-codebase-chat --project <path> --search \"rate limiting\"\n npx dsh-codebase-chat --project <path> --file src/auth.ts\n npx dsh-codebase-chat --project <path> --index\n npx dsh-codebase-chat --project <path> --stats\n npx dsh-codebase-chat --project <path> --health\n npx dsh-codebase-chat --project <path> --impact src/store.ts\n npx dsh-codebase-chat --project <path> --health --diff main\n npx dsh-codebase-chat --project <path> --watch\n\nOptions:\n -p, --project <path> Project directory (default: current directory)\n -a, --ask <question> Ask a question about the codebase\n -s, --search <query> Search code by semantic terms\n -f, --file <path> Focus on a specific file\n -i, --index Force re-index the project\n -t, --stats Print indexing stats\n -H, --health Deterministic static analysis (cycles, dead code, dupes, complexity)\n --impact <file> Blast radius — which files transitively depend on <file>\n -d, --diff <ref> Scope --ask/--search/--health to files changed vs a git ref\n -w, --watch Keep the index hot — rebuild incrementally on file changes\n -e, --embed Enable local semantic embeddings (slower, more relevant)\n --lang <en|fr> Language for headings (default: .codebase-chat.json lang, else fr)\n -h, --help Show this help\n\nConfig:\n .codebase-chat.json Per-project settings: lang, maxTokens, ignoreDirs,\n ignoreFiles, ignoreGlobs, protectedPaths\n\nEnvironment:\n CODEBASE_CACHE_DIR Directory for the index cache\n`);\n}\n\nasync function main() {\n const { values } = parseArgs({\n options: {\n project: { type: 'string', short: 'p', default: '.' },\n ask: { type: 'string', short: 'a' },\n search: { type: 'string', short: 's' },\n file: { type: 'string', short: 'f' },\n index: { type: 'boolean', short: 'i', default: false },\n stats: { type: 'boolean', short: 't', default: false },\n health: { type: 'boolean', short: 'H', default: false },\n impact: { type: 'string' },\n diff: { type: 'string', short: 'd' },\n watch: { type: 'boolean', short: 'w', default: false },\n embed: { type: 'boolean', short: 'e', default: false },\n lang: { type: 'string' },\n help: { type: 'boolean', short: 'h', default: false },\n },\n allowPositionals: false,\n });\n\n if (values.help) {\n printHelp();\n exit(0);\n }\n\n const project = resolveProjectPath(values.project);\n const cfg = await loadProjectConfig(project);\n const lang = values.lang === 'en' || values.lang === 'fr' ? values.lang : (cfg.lang ?? 'fr');\n\n if (values.index) {\n await getIndex(project, m => console.log(m), true);\n exit(0);\n }\n\n if (values.stats) {\n const index = await getIndex(project, m => console.log(m));\n const fileCount = Object.keys(index.files).length;\n const totalTokens = Object.values(index.files).reduce((sum, f) => sum + f.chunks.reduce((s, c) => s + c.tokens, 0), 0);\n const termCount = Object.keys(index.terms).length;\n console.log(`Project: ${index.projectPath}`);\n console.log(`Files: ${fileCount}`);\n console.log(`Tokens: ${totalTokens}`);\n console.log(`Terms: ${termCount}`);\n console.log(`Cache: ${index.projectHash}`);\n exit(0);\n }\n\n if (values.watch) {\n const abs = await findProjectRoot(project);\n const walk = await getWalkOptions(abs);\n await getIndex(abs, m => console.log(m), true);\n console.log(lang === 'en'\n ? 'Watch mode — the index stays hot while you code. (Ctrl+C to quit)'\n : 'Mode watch — l\\u2019index reste à jour pendant que tu codes. (Ctrl+C pour quitter)');\n let timer: NodeJS.Timeout | undefined;\n let pending = new Set<string>();\n const watcher = watch(abs, { recursive: true }, (_event, filename) => {\n if (!filename) return;\n const rel = filename.split(sep).join('/');\n if (rel.split('/').some(p => walk.skipDirs.has(p))) return;\n pending.add(rel);\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n const changed = [...pending];\n pending = new Set();\n const t0 = Date.now();\n // Freshness check rebuilds only the files whose signature changed.\n void getIndex(abs, () => {}).then(() => {\n const dt = ((Date.now() - t0) / 1000).toFixed(1);\n const list = changed.slice(0, 4).join(', ') + (changed.length > 4 ? ` +${changed.length - 4}` : '');\n console.log(lang === 'en'\n ? `Changed: ${list} → index refreshed (${dt}s)`\n : `Modifié : ${list} → index à jour (${dt}s)`);\n });\n }, 500);\n });\n process.on('SIGINT', () => { watcher.close(); exit(0); });\n await new Promise(() => {});\n }\n\n if (values.health) {\n let scope;\n if (values.diff) {\n const s = await getChangedFiles(await findProjectRoot(project), values.diff);\n if (s.ok) {\n scope = { files: s.files };\n console.log(lang === 'en'\n ? `Diff scope: ${s.files.size} file(s) changed vs ${values.diff}`\n : `Périmètre diff : ${s.files.size} fichier(s) modifié(s) vs ${values.diff}`);\n } else {\n console.error(lang === 'en'\n ? `warning: diff vs \"${values.diff}\" unavailable (${s.error}) — full project`\n : `attention : diff vs \"${values.diff}\" indisponible (${s.error}) — projet complet`);\n }\n }\n const report = await analyzeProject(project, scope);\n console.log(formatHealthReport(report, lang));\n exit(0);\n }\n\n if (values.impact) {\n const r = await analyzeImpact(project, values.impact);\n if (!r.ok) {\n console.log(lang === 'en'\n ? r.candidates.length\n ? `Ambiguous target \"${values.impact}\" — candidates:\\n ${r.candidates.join('\\n ')}`\n : `No code file matches \"${values.impact}\".`\n : r.candidates.length\n ? `Cible ambiguë \"${values.impact}\" — candidats :\\n ${r.candidates.join('\\n ')}`\n : `Aucun fichier de code ne correspond à \"${values.impact}\".`);\n exit(1);\n }\n console.log(formatImpactReport(r.report, lang));\n exit(0);\n }\n\n if (values.ask || values.search || values.file) {\n const result = await buildContext({\n project: values.project,\n query: values.ask ?? values.search ?? '',\n searchQuery: values.search,\n filePath: values.file,\n lang,\n embed: values.embed,\n diff: values.diff,\n });\n console.log(result.context);\n console.log(`\\n--- Stats ---`);\n console.log(`Project: ${result.absProject}`);\n console.log(`Chunks: ${result.chunks.length}`);\n console.log(`Tokens: ${result.tokenCount}`);\n exit(0);\n }\n\n printHelp();\n exit(1);\n}\n\nmain().catch(err => {\n disposeTreeSitter();\n if (err instanceof ExitSignal) {\n process.exitCode = err.code;\n return;\n }\n console.error(err?.message ?? err);\n process.exitCode = 1;\n setTimeout(() => process.exit(1), 2000).unref();\n});\n","import { join } from 'node:path';\r\nimport type { ContextOptions, ContextResult, CodeChunk } from './types.js';\r\nimport { countTokens, truncateToTokens } from './tokenizer.js';\r\nimport { embedIndex, getIndex } from './indexer.js';\r\nimport { scoreChunks, selectChunks } from './retriever.js';\r\nimport { findProjectRoot, resolveProjectPath, safeReadText } from './project.js';\r\nimport { loadProjectConfig } from './config.js';\r\nimport { getChangedFiles } from './diff.js';\r\n\r\nconst DEFAULT_MAX_TOKENS = 60_000;\r\nconst HEAD_BUDGET_TOKENS = 800;\r\n\r\ninterface Labels {\r\n project: string;\r\n focus: string;\r\n tree: string;\r\n noConstraints: string;\r\n constraints: string;\r\n answerIn: string;\r\n diffScope: (base: string, n: number) => string;\r\n diffUnavailable: (base: string) => string;\r\n}\r\n\r\nfunction getLabels(lang: 'en' | 'fr'): Labels {\r\n return lang === 'en'\r\n ? {\r\n project: 'Project',\r\n focus: 'Focus',\r\n tree: 'File tree',\r\n noConstraints: 'No explicit constraints documented.',\r\n constraints: 'IDENTIFIED PRODUCT CONSTRAINTS',\r\n answerIn: 'Answer in English.',\r\n diffScope: (base, n) => `Scope: ${n} file(s) changed vs ${base}`,\r\n diffUnavailable: base => `Scope: diff vs ${base} unavailable (not a git repo?) — full project`,\r\n }\r\n : {\r\n project: 'Projet',\r\n focus: 'Focus',\r\n tree: 'Arborescence',\r\n noConstraints: 'Aucune contrainte explicite documentée.',\r\n constraints: 'CONTRAINTES PRODUIT IDENTIFIÉES',\r\n answerIn: 'Réponds obligatoirement en français.',\r\n diffScope: (base, n) => `Périmètre : ${n} fichier(s) modifié(s) vs ${base}`,\r\n diffUnavailable: base => `Périmètre : diff vs ${base} indisponible (pas un repo git ?) — projet complet`,\r\n };\r\n}\r\n\r\nasync function extractProductConstraints(absProject: string): Promise<string[]> {\r\n const candidates = [\r\n 'README.md', 'README.MD', 'readme.md', 'MEMORY.md', 'CONTRIBUTING.md',\r\n 'AGENTS.md', 'CLAUDE.md', '.windsurfrules', '.cursorrules', '.cursorrules.md',\r\n ];\r\n const constraints: string[] = [];\r\n for (const name of candidates) {\r\n const text = await safeReadText(join(absProject, name));\r\n if (!text) continue;\r\n const regex = /(?:constraint|contrainte|must|doit|interdit|forbidden|rule|règle|limitation|never|always|jamais|toujours|zéro|zero)[\\s\\S]{0,200}/gi;\r\n let m;\r\n while ((m = regex.exec(text)) !== null) {\r\n const line = m[0].replace(/\\s+/g, ' ').trim();\r\n if (line.length > 20) constraints.push(`[${name}] ${line}`);\r\n }\r\n }\r\n return constraints.slice(0, 12);\r\n}\r\n\r\nfunction formatChunk(chunk: CodeChunk): string {\r\n const kind = chunk.kind.toUpperCase();\r\n const source = `[source: ${chunk.relPath}:${chunk.startLine}-${chunk.endLine}]`;\r\n const kindLabel = chunk.kind === 'unknown' ? '' : ` (${kind})`;\r\n const header = `--- ${chunk.relPath}${chunk.name ? ` :: ${chunk.name}` : ''}${kindLabel} ${source} ---`;\r\n return `${header}\\n${chunk.content}`;\r\n}\r\n\r\nexport async function buildContext(options: ContextOptions): Promise<ContextResult> {\r\n const { project, query, filePath, searchQuery, instruction, embed = false, diff } = options;\r\n const absProject = await findProjectRoot(resolveProjectPath(project));\r\n const cfg = await loadProjectConfig(absProject);\r\n const maxTokens = options.maxTokens ?? cfg.maxTokens ?? DEFAULT_MAX_TOKENS;\r\n const lang = options.lang ?? cfg.lang ?? 'fr';\r\n const labels = getLabels(lang);\r\n const index = await getIndex(absProject);\r\n\r\n // --diff <base> — restrict retrieval to files changed vs the git ref.\r\n // The inverted index needs no rebuild: postings for out-of-scope files are\r\n // skipped by the index.files lookup during scoring.\r\n let scopedIndex = index;\r\n let diffFiles: string[] | undefined;\r\n let scopeLine = '';\r\n if (diff && !filePath) {\r\n const scope = await getChangedFiles(absProject, diff);\r\n if (scope.ok) {\r\n diffFiles = [...scope.files].filter(f => index.files[f]);\r\n const files: typeof index.files = {};\r\n for (const f of diffFiles) files[f] = index.files[f];\r\n scopedIndex = { ...index, files };\r\n scopeLine = `${labels.diffScope(diff, diffFiles.length)}\\n`;\r\n } else {\r\n scopeLine = `${labels.diffUnavailable(diff)}\\n`;\r\n }\r\n }\r\n\r\n if (embed) {\r\n try {\r\n await embedIndex(index);\r\n } catch {\r\n // embeddings are optional: fallback to lexical if the model is unavailable\r\n }\r\n }\r\n\r\n const focus = filePath ?? searchQuery ?? query;\r\n\r\n let selectedChunks: CodeChunk[] = [];\r\n\r\n const bodyLimit = maxTokens - HEAD_BUDGET_TOKENS;\r\n const maxChunkTokens = Math.floor(bodyLimit / 2);\r\n\r\n if (filePath) {\r\n const all = Object.values(index.files);\r\n const target =\r\n all.find(f => f.relPath === filePath) ??\r\n all.filter(f => f.relPath.endsWith(`/${filePath}`) || f.relPath.endsWith(filePath))\r\n .sort((a, b) => a.relPath.length - b.relPath.length)[0];\r\n if (target) {\r\n const { chunks } = selectChunks(\r\n target.chunks.map(c => ({ ...c, score: 0 })),\r\n bodyLimit,\r\n Infinity\r\n );\r\n selectedChunks = chunks;\r\n } else {\r\n // Not a file path — treat it as a symbol/term and search instead of failing.\r\n const scored = await scoreChunks(scopedIndex, filePath, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n if (chunks.length === 0) throw new Error(`File not found: ${filePath}`);\r\n selectedChunks = chunks;\r\n }\r\n } else if (searchQuery) {\r\n const scored = await scoreChunks(scopedIndex, searchQuery, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n selectedChunks = chunks;\r\n } else {\r\n const scored = await scoreChunks(scopedIndex, query, embed);\r\n const { chunks } = selectChunks(scored, bodyLimit, maxChunkTokens);\r\n selectedChunks = chunks;\r\n }\r\n\r\n const constraints = await extractProductConstraints(absProject);\r\n const constraintsText = constraints.length\r\n ? `== ${labels.constraints} ==\\n${constraints.map(c => `- ${c}`).join('\\n')}`\r\n : `== ${labels.constraints} ==\\n${labels.noConstraints}`;\r\n\r\n const head = `${labels.project} : ${absProject}\\n${labels.focus} : ${focus}\\n${scopeLine}${constraintsText}\\n\\n== ${labels.tree} ==\\n${index.tree}\\n`;\r\n const headTokens = countTokens(head);\r\n\r\n const body = selectedChunks.map(c => formatChunk(c)).join('\\n\\n');\r\n const bodyBudget = Math.max(0, maxTokens - headTokens - 100);\r\n const truncatedBody = truncateToTokens(body, bodyBudget);\r\n\r\n const baseInstruction = `${labels.answerIn}\\nAnswer the question or perform the requested task using the code context above. Cite every technical claim with [source: relative/path:line]. Provide confidence and severity where relevant.`;\r\n const finalInstruction = instruction ? `${instruction}\\n\\n${baseInstruction}` : baseInstruction;\r\n const prompt = `${head}\\n\\n${truncatedBody}\\n\\n${finalInstruction}`;\r\n\r\n const tokenCount = countTokens(prompt);\r\n\r\n return {\r\n absProject,\r\n context: prompt,\r\n chunks: selectedChunks,\r\n tokenCount,\r\n diffFiles,\r\n };\r\n}\r\n","import { encode, decode } from 'gpt-tokenizer';\r\n\r\n/**\r\n * Count the exact number of tokens for a given text using the CL100K base\r\n * tokenizer (used by GPT-4 / o1 / Claude / DeepSeek-v3).\r\n */\r\nexport function countTokens(text: string): number {\r\n return encode(text).length;\r\n}\r\n\r\n/**\r\n * Split a text into token chunks of at most `maxTokens`.\r\n * Tries to keep whole lines when possible.\r\n */\r\nexport function chunkByTokens(text: string, maxTokens: number, overlapTokens = 0): string[] {\r\n if (maxTokens <= 0) throw new RangeError('maxTokens must be positive');\r\n\r\n const tokens = encode(text);\r\n const chunks: string[] = [];\r\n const step = maxTokens - overlapTokens;\r\n\r\n for (let i = 0; i < tokens.length; i += step) {\r\n const end = Math.min(i + maxTokens, tokens.length);\r\n const slice = tokens.slice(i, end);\r\n chunks.push(decode(slice));\r\n if (end === tokens.length) break;\r\n }\r\n\r\n return chunks;\r\n}\r\n\r\n/**\r\n * Truncate a text to a maximum number of tokens, appending an ellipsis if truncated.\r\n */\r\nexport function truncateToTokens(text: string, maxTokens: number): string {\r\n const tokens = encode(text);\r\n if (tokens.length <= maxTokens) return text;\r\n const keep = Math.max(0, maxTokens - 5);\r\n const truncated = tokens.slice(0, keep);\r\n return `${decode(truncated)} [...]`;\r\n}\r\n","import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';\r\nimport { dirname, join, relative, sep } from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport type { CodeIndex, IndexedFile, InvertedIndex } from './types.js';\r\nimport { extractChunks } from './extractor.js';\r\nimport { ensureTreeSitterForExt } from './treesitter.js';\r\nimport { countTokens } from './tokenizer.js';\r\nimport { getEmbeddings } from './embeddings.js';\r\nimport {\r\n buildTree,\r\n cacheFilePath,\r\n fileHash,\r\n findProjectRoot,\r\n getWalkOptions,\r\n projectHash,\r\n resolveProjectPath,\r\n safeReadText,\r\n walkFiles,\r\n} from './project.js';\r\n\r\nconst INDEX_VERSION = 5;\r\n\r\nconst STOP_WORDS = new Set([\r\n 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought', 'used', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'and', 'or', 'but', 'so', 'yet', 'a', 'an', 'this', 'that', 'these', 'those', 'it', 'its', 'he', 'she', 'they', 'them', 'their', 'we', 'us', 'our', 'you', 'your', 'i', 'me', 'my', 'le', 'la', 'les', 'un', 'une', 'des', 'du', 'de', 'et', 'ou', 'que', 'qui', 'quoi', 'dont', 'ce', 'cet', 'cette', 'ces', 'est', 'sont', 'etait', 'etaient', 'avoir', 'etre', 'faire', 'dans', 'pour', 'sur', 'avec', 'par', 'a', 'au', 'aux'\r\n]);\r\n\r\nfunction tokenizeTerms(text: string): string[] {\r\n return text\r\n .replace(/[^a-zA-Z0-9\\u00C0-\\u017F]+/g, ' ')\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter(Boolean)\r\n .filter(t => t.length > 1 && !STOP_WORDS.has(t));\r\n}\r\n\r\nfunction buildInvertedIndex(files: Record<string, IndexedFile>): InvertedIndex {\r\n const index: InvertedIndex = {};\r\n for (const file of Object.values(files)) {\r\n for (const chunk of file.chunks) {\r\n const terms = new Set([\r\n ...tokenizeTerms(chunk.content),\r\n ...tokenizeTerms(chunk.relPath),\r\n ...tokenizeTerms(chunk.name ?? ''),\r\n ]);\r\n for (const term of terms) {\r\n if (!index[term]) index[term] = {};\r\n if (!index[term][file.relPath]) index[term][file.relPath] = 0;\r\n index[term][file.relPath] += 1;\r\n }\r\n }\r\n }\r\n return index;\r\n}\r\n\r\nexport async function loadIndex(projectPath: string): Promise<CodeIndex | null> {\r\n const absProject = await findProjectRoot(resolveProjectPath(projectPath));\r\n const p = cacheFilePath(absProject);\r\n if (!existsSync(p)) return null;\r\n try {\r\n const raw = await readFile(p, 'utf8');\r\n const data = JSON.parse(raw) as CodeIndex;\r\n if (data.version !== INDEX_VERSION) return null;\r\n return data;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport async function saveIndex(index: CodeIndex): Promise<void> {\r\n const p = cacheFilePath(index.projectPath);\r\n await mkdir(dirname(p), { recursive: true });\r\n await writeFile(p, JSON.stringify(index), 'utf8');\r\n}\r\n\r\nexport async function embedIndex(index: CodeIndex, progress?: (message: string) => void): Promise<void> {\r\n const allChunks = Object.values(index.files).flatMap(f => f.chunks);\r\n const missing = allChunks.filter(c => !c.embedding || c.embedding.length === 0);\r\n if (missing.length === 0) return;\r\n\r\n const batchSize = 32;\r\n for (let i = 0; i < missing.length; i += batchSize) {\r\n const batch = missing.slice(i, i + batchSize);\r\n progress?.(`Embedding ${i + batch.length}/${missing.length} chunks...`);\r\n try {\r\n const vectors = await getEmbeddings(batch.map(c => c.content));\r\n for (let j = 0; j < batch.length; j++) {\r\n batch[j].embedding = vectors[j];\r\n }\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n progress?.(`Embedding failed: ${msg}`);\r\n break;\r\n }\r\n }\r\n\r\n await saveIndex(index);\r\n}\r\n\r\nexport async function buildIndex(projectPath: string, progress?: (message: string) => void): Promise<CodeIndex> {\r\n const absProject = await findProjectRoot(resolveProjectPath(projectPath));\r\n const projectName = absProject.split(sep).pop() ?? 'project';\r\n\r\n progress?.(`Indexing ${projectName}...`);\r\n\r\n const walk = await getWalkOptions(absProject);\r\n const tree = await buildTree(absProject, undefined, walk.skipDirs);\r\n const startDir = absProject;\r\n const previous = await loadIndex(absProject);\r\n const previousFiles = previous?.projectPath === absProject ? previous.files : {};\r\n const files: Record<string, IndexedFile> = {};\r\n let totalTokens = 0;\r\n let reused = 0;\r\n\r\n for await (const fullPath of walkFiles(startDir, walk.skipDirs, walk.skipFiles, walk.ignoreGlobs)) {\r\n const relPath = relative(startDir, fullPath).split(sep).join('/');\r\n progress?.(`Reading ${relPath}`);\r\n\r\n const fstats = await stat(fullPath);\r\n\r\n // Reuse cached chunks when the file signature is unchanged (mtime + size).\r\n const cached = previousFiles[relPath];\r\n if (cached && cached.mtimeMs === fstats.mtimeMs && cached.size === fstats.size) {\r\n files[relPath] = cached;\r\n reused++;\r\n totalTokens += cached.chunks.reduce((sum, c) => sum + c.tokens, 0);\r\n continue;\r\n }\r\n\r\n const text = await safeReadText(fullPath);\r\n if (!text) continue;\r\n\r\n const hash = fileHash(fstats, text);\r\n\r\n // Lazy-load the tree-sitter grammar for this extension (cached after first call).\r\n const ext = relPath.slice(relPath.lastIndexOf('.')).toLowerCase();\r\n await ensureTreeSitterForExt(ext);\r\n\r\n const chunks = extractChunks(relPath, text).map(chunk => ({\r\n ...chunk,\r\n // recompute tokens to be safe\r\n tokens: countTokens(chunk.content),\r\n }));\r\n\r\n totalTokens += chunks.reduce((sum, c) => sum + c.tokens, 0);\r\n\r\n files[relPath] = {\r\n relPath,\r\n size: fstats.size,\r\n mtimeMs: fstats.mtimeMs,\r\n hash,\r\n chunks,\r\n };\r\n }\r\n\r\n const now = Date.now();\r\n const index: CodeIndex = {\r\n projectPath: absProject,\r\n projectHash: projectHash(absProject),\r\n version: INDEX_VERSION,\r\n createdAt: previous?.createdAt ?? now,\r\n updatedAt: now,\r\n tree,\r\n constraints: [],\r\n files,\r\n terms: buildInvertedIndex(files),\r\n };\r\n\r\n await saveIndex(index);\r\n progress?.(`Indexed ${Object.keys(files).length} files, ~${totalTokens} tokens${reused ? ` (${reused} unchanged reused)` : ''}`);\r\n return index;\r\n}\r\n\r\nexport async function getIndex(projectPath: string, progress?: (message: string) => void, force = false): Promise<CodeIndex> {\r\n const resolved = resolveProjectPath(projectPath);\r\n const absProject = await findProjectRoot(resolved);\r\n const existing = force ? null : await loadIndex(resolved);\r\n if (existing && existing.projectPath === absProject) {\r\n // Fast freshness check: mtime + size only, no file reads.\r\n let stale = false;\r\n for (const file of Object.values(existing.files)) {\r\n const fullPath = join(absProject, file.relPath);\r\n try {\r\n const fstats = await stat(fullPath);\r\n if (fstats.mtimeMs !== file.mtimeMs || fstats.size !== file.size) {\r\n stale = true;\r\n break;\r\n }\r\n } catch {\r\n stale = true;\r\n break;\r\n }\r\n }\r\n if (!stale) {\r\n progress?.('Loaded index from cache');\r\n return existing;\r\n }\r\n }\r\n return buildIndex(projectPath, progress);\r\n}\r\n\r\n\r\n","import { parse } from '@babel/parser';\r\nimport traverse from '@babel/traverse';\r\nimport * as t from '@babel/types';\r\nimport type { CodeChunk } from './types.js';\r\nimport { countTokens } from './tokenizer.js';\r\nimport { mergeGaps } from './merge-gaps.js';\r\nimport { extractWithTreeSitter, treeSitterReady } from './treesitter.js';\r\n\r\nconst JS_LIKE = new Set([\r\n '.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx'\r\n]);\r\n\r\ninterface BabelNode {\r\n loc?: { start: { line: number }; end: { line: number } } | null;\r\n}\r\n\r\nfunction getName(node: BabelNode & t.Node): string | undefined {\r\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isTSInterfaceDeclaration(node) || t.isTSTypeAliasDeclaration(node)) {\r\n return node.id?.name;\r\n }\r\n if (t.isVariableDeclaration(node)) {\r\n const first = node.declarations[0];\r\n if (first && t.isIdentifier(first.id)) return first.id.name;\r\n }\r\n if (t.isObjectMethod(node) || t.isClassMethod(node) || t.isClassPrivateMethod(node)) {\r\n const key = node.key as any;\r\n if (t.isIdentifier(node.key) || t.isStringLiteral(node.key) || t.isNumericLiteral(node.key)) {\r\n return String(key.name ?? key.value ?? 'anonymous');\r\n }\r\n if (t.isPrivateName(node.key)) {\r\n return (node.key.id as any)?.name;\r\n }\r\n }\r\n if (t.isExportNamedDeclaration(node) && node.declaration) {\r\n return getName(node.declaration as t.Node);\r\n }\r\n if (t.isExportDefaultDeclaration(node) && node.declaration) {\r\n if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {\r\n return getName(node.declaration) ?? 'default';\r\n }\r\n if (t.isVariableDeclaration(node.declaration)) {\r\n return getName(node.declaration) ?? 'default';\r\n }\r\n return 'default';\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction getKind(node: t.Node): CodeChunk['kind'] {\r\n if (t.isClassMethod(node) || t.isClassPrivateMethod(node) || t.isObjectMethod(node)) return 'method';\r\n if (t.isFunctionDeclaration(node) || t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) return 'function';\r\n if (t.isClassDeclaration(node) || t.isClassExpression(node)) return 'class';\r\n if (t.isTSInterfaceDeclaration(node) || t.isTSTypeAliasDeclaration(node)) return 'type';\r\n if (t.isImportDeclaration(node) || t.isExportAllDeclaration(node) || t.isExportNamespaceSpecifier(node)) return 'import';\r\n if (t.isVariableDeclaration(node)) return 'unknown';\r\n if (t.isExportNamedDeclaration(node) && node.declaration) return getKind(node.declaration);\r\n if (t.isExportDefaultDeclaration(node) && node.declaration) return getKind(node.declaration);\r\n if (t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node)) return 'import';\r\n return 'unknown';\r\n}\r\n\r\nfunction sliceLines(content: string, start: number, end: number): string {\r\n const lines = content.split('\\n');\r\n return lines.slice(start - 1, end).join('\\n');\r\n}\r\n\r\nfunction extractTopLevelWithBabel(relPath: string, content: string): CodeChunk[] {\r\n const ast = parse(content, {\r\n sourceType: 'module',\r\n allowImportExportEverywhere: true,\r\n allowReturnOutsideFunction: true,\r\n plugins: [\r\n 'typescript',\r\n 'jsx',\r\n 'decorators-legacy',\r\n 'classProperties',\r\n 'asyncGenerators',\r\n 'bigInt',\r\n 'dynamicImport',\r\n 'exportDefaultFrom',\r\n 'nullishCoalescingOperator',\r\n 'numericSeparator',\r\n 'objectRestSpread',\r\n 'optionalCatchBinding',\r\n 'optionalChaining',\r\n 'topLevelAwait',\r\n ] as any,\r\n });\r\n\r\n const chunks: CodeChunk[] = [];\r\n const visitedRanges: [number, number][] = [];\r\n\r\n traverse(ast, {\r\n enter(path) {\r\n const node = path.node;\r\n if (\r\n t.isFunctionDeclaration(node) ||\r\n t.isClassDeclaration(node) ||\r\n t.isTSInterfaceDeclaration(node) ||\r\n t.isTSTypeAliasDeclaration(node) ||\r\n t.isVariableDeclaration(node) ||\r\n t.isImportDeclaration(node) ||\r\n t.isExportNamedDeclaration(node) ||\r\n t.isExportDefaultDeclaration(node) ||\r\n t.isExportAllDeclaration(node)\r\n ) {\r\n const loc = node.loc;\r\n if (!loc) return;\r\n // Avoid duplicate nested traversal: only consider top-level declarations\r\n if (path.parentPath && !t.isProgram(path.parentPath.node)) return;\r\n\r\n // Class methods\r\n if (t.isClassDeclaration(node) && node.body?.body) {\r\n for (const member of node.body.body) {\r\n if (!member.loc) continue;\r\n if (t.isClassMethod(member) || t.isClassPrivateMethod(member) || t.isClassProperty(member)) {\r\n const methodChunk: CodeChunk = {\r\n relPath,\r\n startLine: member.loc.start.line,\r\n endLine: member.loc.end.line,\r\n content: sliceLines(content, member.loc.start.line, member.loc.end.line),\r\n tokens: 0,\r\n kind: getKind(member),\r\n name: getName(member as t.Node),\r\n };\r\n methodChunk.tokens = countTokens(methodChunk.content);\r\n chunks.push(methodChunk);\r\n }\r\n }\r\n }\r\n\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: loc.start.line,\r\n endLine: loc.end.line,\r\n content: sliceLines(content, loc.start.line, loc.end.line),\r\n tokens: 0,\r\n kind: getKind(node),\r\n name: getName(node),\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n visitedRanges.push([loc.start.line, loc.end.line]);\r\n }\r\n },\r\n });\r\n\r\n return mergeGaps(content, relPath, chunks, visitedRanges);\r\n}\r\n\r\n/**\r\n * Gap-filling between named chunks lives in merge-gaps.ts — it is shared\r\n * by the Babel and tree-sitter extraction paths.\r\n */\r\n\r\nfunction extractWithRegex(relPath: string, content: string): CodeChunk[] {\r\n const lines = content.split('\\n');\r\n const chunks: CodeChunk[] = [];\r\n let currentStart = 1;\r\n let currentLines: string[] = [];\r\n\r\n // Simple heuristic: split on blank lines or lines starting with `function`, `class`, `const`, etc.\r\n const re = /^(export\\s+)?(?:async\\s+)?(?:function\\s+\\w+|class\\s+\\w+|const\\s+\\w+|let\\s+\\w+|var\\s+\\w+|interface\\s+\\w+|type\\s+\\w+|def\\s+\\w+|struct\\s+\\w+|fn\\s+\\w+)/;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line.match(re) && currentLines.length > 0) {\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: currentStart,\r\n endLine: i,\r\n content: currentLines.join('\\n'),\r\n tokens: 0,\r\n kind: 'unknown',\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n currentStart = i + 1;\r\n currentLines = [line];\r\n } else {\r\n currentLines.push(line);\r\n }\r\n }\r\n\r\n if (currentLines.length) {\r\n const chunk: CodeChunk = {\r\n relPath,\r\n startLine: currentStart,\r\n endLine: lines.length,\r\n content: currentLines.join('\\n'),\r\n tokens: 0,\r\n kind: 'unknown',\r\n };\r\n chunk.tokens = countTokens(chunk.content);\r\n chunks.push(chunk);\r\n }\r\n\r\n return chunks.filter(c => c.content.trim());\r\n}\r\n\r\n/**\r\n * Extract semantically meaningful chunks from a source file.\r\n * Uses Babel for JS/TS, tree-sitter for Python/Go/Rust/Java/C#/PHP\r\n * (when grammars are loaded via `ensureTreeSitterForExt`), and a\r\n * regex fallback for everything else.\r\n */\r\nexport function extractChunks(relPath: string, content: string): CodeChunk[] {\r\n const ext = relPath.slice(relPath.lastIndexOf('.')).toLowerCase();\r\n if (JS_LIKE.has(ext)) {\r\n try {\r\n return extractTopLevelWithBabel(relPath, content);\r\n } catch {\r\n // Fall back to regex if Babel fails (e.g. malformed code)\r\n return extractWithRegex(relPath, content);\r\n }\r\n }\r\n if (treeSitterReady(ext)) {\r\n try {\r\n const chunks = extractWithTreeSitter(ext, relPath, content);\r\n if (chunks && chunks.length) return chunks;\r\n } catch {\r\n // fall through to regex\r\n }\r\n }\r\n return extractWithRegex(relPath, content);\r\n}\r\n","import type { CodeChunk } from './types.js';\nimport { countTokens } from './tokenizer.js';\n\n/**\n * Add 'file' chunks covering lines not already in a named chunk,\n * so nothing is lost from the original file.\n */\nexport function mergeGaps(content: string, relPath: string, namedChunks: CodeChunk[], visitedRanges: [number, number][]): CodeChunk[] {\n const lines = content.split('\\n');\n if (lines.length === 0) return namedChunks;\n\n const covered = new Set<number>();\n for (const [start, end] of visitedRanges) {\n for (let i = start; i <= end; i++) covered.add(i);\n }\n\n const all: CodeChunk[] = [];\n let start = 1;\n for (let i = 1; i <= lines.length; i++) {\n if (!covered.has(i)) continue;\n if (i > start) {\n const gapText = lines.slice(start - 1, i - 1).join('\\n');\n if (gapText.trim()) all.push({ relPath, startLine: start, endLine: i - 1, content: gapText, tokens: countTokens(gapText), kind: 'file' });\n }\n start = i + 1;\n }\n if (start <= lines.length) {\n const gapText = lines.slice(start - 1).join('\\n');\n if (gapText.trim()) all.push({ relPath, startLine: start, endLine: lines.length, content: gapText, tokens: countTokens(gapText), kind: 'file' });\n }\n\n return [...all, ...namedChunks].sort((a, b) => a.startLine - b.startLine);\n}\n","import { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport type Parser from 'web-tree-sitter';\nimport type { CodeChunk } from './types.js';\nimport { countTokens } from './tokenizer.js';\nimport { mergeGaps } from './merge-gaps.js';\n\nconst require = createRequire(import.meta.url);\n\n/** File extension → tree-sitter-wasms grammar name. */\nconst GRAMMAR_BY_EXT: Record<string, string> = {\n '.py': 'python',\n '.go': 'go',\n '.rs': 'rust',\n '.java': 'java',\n '.cs': 'c_sharp',\n '.php': 'php',\n};\n\n/** node type → chunk kind, per grammar. */\nconst DECL_TYPES: Record<string, Record<string, CodeChunk['kind']>> = {\n python: {\n function_definition: 'function',\n class_definition: 'class',\n },\n go: {\n function_declaration: 'function',\n method_declaration: 'method',\n type_declaration: 'type',\n import_declaration: 'import',\n const_declaration: 'unknown',\n var_declaration: 'unknown',\n },\n rust: {\n function_item: 'function',\n struct_item: 'type',\n enum_item: 'type',\n union_item: 'type',\n trait_item: 'type',\n type_item: 'type',\n impl_item: 'type',\n mod_item: 'unknown',\n use_declaration: 'import',\n macro_definition: 'unknown',\n },\n java: {\n class_declaration: 'class',\n interface_declaration: 'type',\n enum_declaration: 'type',\n record_declaration: 'type',\n annotation_type_declaration: 'type',\n method_declaration: 'method',\n constructor_declaration: 'method',\n field_declaration: 'unknown',\n import_declaration: 'import',\n package_declaration: 'import',\n },\n c_sharp: {\n class_declaration: 'class',\n interface_declaration: 'type',\n struct_declaration: 'type',\n enum_declaration: 'type',\n record_declaration: 'type',\n delegate_declaration: 'type',\n method_declaration: 'method',\n constructor_declaration: 'method',\n property_declaration: 'method',\n field_declaration: 'unknown',\n using_directive: 'import',\n },\n php: {\n function_definition: 'function',\n class_declaration: 'class',\n interface_declaration: 'type',\n trait_declaration: 'type',\n enum_declaration: 'type',\n method_declaration: 'method',\n namespace_use_declaration: 'import',\n namespace_definition: 'unknown',\n },\n};\n\n/** Node types whose named children may contain more declarations. */\nconst RECURSE_INTO = new Set([\n 'program', 'module', 'translation_unit', 'compilation_unit', 'source_file',\n 'namespace_declaration', 'file_scoped_namespace_declaration', 'namespace_definition',\n 'declaration_list', 'decorated_definition', 'export_statement',\n]);\n\n/** Node types that act as member containers (methods/functions inside). */\nconst CONTAINER_TYPES = new Set([\n 'class_definition', 'class_declaration', 'interface_declaration',\n 'enum_declaration', 'record_declaration', 'struct_declaration',\n 'impl_item', 'trait_item', 'trait_declaration',\n]);\n\n/** Member node types emitted as 'method' chunks inside containers. */\nconst MEMBER_TYPES = new Set([\n 'function_definition', 'method_declaration', 'method_definition',\n 'function_item', 'constructor_declaration', 'property_declaration',\n]);\n\n/** Identifier-ish node types used as a name fallback. */\nconst NAME_TYPES = new Set([\n 'identifier', 'type_identifier', 'field_identifier', 'simple_type', 'name',\n]);\n\ntype TreeSitterModule = typeof Parser & { default?: typeof Parser };\n\nlet parser: Parser | null = null;\nlet initPromise: Promise<boolean> | null = null;\nconst languages = new Map<string, Parser.Language | null>();\nconst langPromises = new Map<string, Promise<Parser.Language | null>>();\n\n/** Initialize the WASM runtime once. Returns false when unavailable. */\nexport async function initTreeSitter(): Promise<boolean> {\n if (parser) return true;\n initPromise ??= (async () => {\n try {\n const mod = (await import('web-tree-sitter')) as unknown as TreeSitterModule;\n const ParserClass = mod.default ?? mod;\n // The .wasm lives next to the installed package, not next to dist/.\n const wasm = require.resolve('web-tree-sitter/tree-sitter.wasm');\n await ParserClass.init({ locateFile: () => wasm });\n parser = new ParserClass();\n return true;\n } catch {\n return false;\n }\n })();\n return initPromise;\n}\n\nfunction grammarPath(name: string): string {\n const pkg = require.resolve('tree-sitter-wasms/package.json');\n return join(dirname(pkg), 'out', `tree-sitter-${name}.wasm`);\n}\n\nasync function ensureLanguage(name: string): Promise<Parser.Language | null> {\n if (languages.has(name)) return languages.get(name)!;\n let p = langPromises.get(name);\n if (!p) {\n p = (async () => {\n try {\n const mod = (await import('web-tree-sitter')) as unknown as TreeSitterModule;\n const ParserClass = mod.default ?? mod;\n const lang = await ParserClass.Language.load(grammarPath(name));\n languages.set(name, lang);\n return lang;\n } catch {\n languages.set(name, null);\n return null;\n }\n })();\n langPromises.set(name, p);\n }\n return p;\n}\n\n/**\n * Make sure the grammar for `ext` is loaded (if the extension is supported).\n * Safe to call per file — repeated calls are cached.\n */\nexport async function ensureTreeSitterForExt(ext: string): Promise<boolean> {\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()];\n if (!name) return false;\n if (!(await initTreeSitter())) return false;\n return (await ensureLanguage(name)) != null;\n}\n\n/** Release the WASM parser — call before process exit to avoid libuv asserts. */\nexport function disposeTreeSitter(): void {\n try { parser?.delete(); } catch { /* best effort */ }\n parser = null;\n initPromise = null;\n languages.clear();\n langPromises.clear();\n}\n\n/** True when a grammar is loaded and ready for synchronous extraction. */\nexport function treeSitterReady(ext: string): boolean {\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()];\n return !!name && !!parser && languages.get(name) != null;\n}\n\nfunction nodeName(node: Parser.SyntaxNode): string | undefined {\n const named = node.childForFieldName('name');\n if (named) return named.text;\n for (const child of node.namedChildren) {\n if (NAME_TYPES.has(child.type)) return child.text;\n // Go: type_declaration → type_spec (name field)\n const inner = child.childForFieldName('name');\n if (inner) return inner.text;\n }\n return undefined;\n}\n\nfunction toChunk(node: Parser.SyntaxNode, kind: CodeChunk['kind'], relPath: string, content: string, name?: string): CodeChunk {\n const startLine = node.startPosition.row + 1;\n const endLine = node.endPosition.row + 1;\n const text = content.split('\\n').slice(startLine - 1, endLine).join('\\n');\n return { relPath, startLine, endLine, content: text, tokens: countTokens(text), kind, name };\n}\n\n/**\n * Extract declaration chunks with tree-sitter. Only call when\n * `treeSitterReady(ext)` is true; returns undefined on parse failure.\n */\nexport function extractWithTreeSitter(ext: string, relPath: string, content: string): CodeChunk[] | undefined {\n if (!parser || !treeSitterReady(ext)) return undefined;\n const name = GRAMMAR_BY_EXT[ext.toLowerCase()]!;\n const lang = languages.get(name)!;\n const declTypes = DECL_TYPES[name] ?? {};\n\n let tree: Parser.Tree;\n try {\n parser.setLanguage(lang);\n tree = parser.parse(content);\n } catch {\n return undefined;\n }\n if (!tree) return undefined;\n\n try {\n const chunks: CodeChunk[] = [];\n const visitedRanges: [number, number][] = [];\n\n const handle = (child: Parser.SyntaxNode) => {\n const kind = declTypes[child.type];\n if (kind) {\n // Python decorators: widen the range to include decorator lines.\n const target = child.parent?.type === 'decorated_definition' ? child.parent : child;\n chunks.push(toChunk(target, kind, relPath, content, nodeName(child)));\n visitedRanges.push([target.startPosition.row + 1, target.endPosition.row + 1]);\n\n // Members of class-like containers become their own 'method' chunks.\n if (CONTAINER_TYPES.has(child.type)) {\n const body = child.childForFieldName('body') ?? child;\n for (const member of body.namedChildren) {\n if (MEMBER_TYPES.has(member.type)) {\n chunks.push(toChunk(member, 'method', relPath, content, nodeName(member)));\n } else if (declTypes[member.type]) {\n // Nested decls (e.g. enum inside class) — keep them too.\n handle(member);\n }\n }\n }\n return;\n }\n if (RECURSE_INTO.has(child.type) || child.namedChildren.some((c) => declTypes[c.type] || RECURSE_INTO.has(c.type))) {\n visit(child);\n }\n };\n\n const visit = (node: Parser.SyntaxNode) => {\n for (const child of node.namedChildren) handle(child);\n };\n visit(tree.rootNode);\n\n return mergeGaps(content, relPath, chunks, visitedRanges);\n } finally {\n tree.delete();\n }\n}\n\n\n","import { pipeline, type FeatureExtractionPipeline } from '@xenova/transformers';\r\nimport { chunkByTokens, countTokens } from './tokenizer.js';\r\n\r\nconst DEFAULT_MODEL = 'Xenova/paraphrase-multilingual-MiniLM-L12-v2';\r\n\r\nlet extractor: FeatureExtractionPipeline | null = null;\r\nlet activeModel = '';\r\n\r\nexport async function getExtractor(model = DEFAULT_MODEL): Promise<FeatureExtractionPipeline> {\r\n if (extractor && activeModel === model) return extractor;\r\n activeModel = model;\r\n extractor = await pipeline('feature-extraction', model, {\r\n quantized: true,\r\n });\r\n return extractor;\r\n}\r\n\r\n/** Truncate long texts to a token budget before embedding. */\r\nfunction prepareText(text: string, maxTokens = 256): string {\r\n if (countTokens(text) <= maxTokens) return text;\r\n return chunkByTokens(text, maxTokens)[0] ?? text.slice(0, 1024);\r\n}\r\n\r\nfunction tensorToVectors(tensor: { dims: number[]; data: Float32Array }): number[][] {\r\n const [count, dim] = tensor.dims;\r\n const vectors: number[][] = [];\r\n for (let i = 0; i < count; i++) {\r\n vectors.push(Array.from(tensor.data.subarray(i * dim, (i + 1) * dim)));\r\n }\r\n return vectors;\r\n}\r\n\r\n/** Compute a single embedding. */\r\nexport async function getEmbedding(text: string, model = DEFAULT_MODEL): Promise<number[]> {\r\n const pipe = await getExtractor(model);\r\n const out = (await pipe(prepareText(text), {\r\n pooling: 'mean',\r\n normalize: true,\r\n })) as unknown as { data: Float32Array };\r\n return Array.from(out.data);\r\n}\r\n\r\n/** Compute embeddings for many texts in one call. */\r\nexport async function getEmbeddings(texts: string[], model = DEFAULT_MODEL): Promise<number[][]> {\r\n const pipe = await getExtractor(model);\r\n const inputs = texts.map(t => prepareText(t));\r\n const out = (await pipe(inputs, {\r\n pooling: 'mean',\r\n normalize: true,\r\n })) as unknown as { dims: number[]; data: Float32Array };\r\n return tensorToVectors(out);\r\n}\r\n\r\n/** Cosine similarity of two normalized vectors (or any vectors). */\r\nexport function cosineSimilarity(a: number[], b: number[]): number {\r\n let dot = 0;\r\n for (let i = 0; i < a.length; i++) {\r\n dot += a[i] * b[i];\r\n }\r\n return dot;\r\n}\r\n","import { readdir, readFile, stat } from 'node:fs/promises';\r\nimport { extname, join, relative, resolve, sep, isAbsolute } from 'node:path';\r\nimport { createHash } from 'node:crypto';\r\nimport { homedir } from 'node:os';\r\nimport { loadProjectConfig, matchesAnyGlob, type ProjectConfig } from './config.js';\r\n\r\nexport interface TreeOptions {\r\n maxLines?: number;\r\n skipDirs?: Set<string>;\r\n}\r\n\r\nconst SOURCE_EXTS = new Set([\r\n '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',\r\n '.vue', '.svelte', '.py', '.rs', '.go', '.java', '.kt',\r\n '.swift', '.cs', '.cpp', '.c', '.h', '.hpp',\r\n '.css', '.scss', '.less', '.html', '.json', '.yaml', '.yml', '.md'\r\n]);\r\n\r\nconst DEFAULT_SKIP_DIRS = new Set([\r\n 'node_modules', '.git', 'dist', 'build', 'out', '.output',\r\n 'coverage', 'tmp', 'temp', '.cache', '.turbo', '.next',\r\n 'android', 'ios', 'e2e-shots', 'playstore_screenshots',\r\n '.cursor', '.idea', '.memsearch', '.vscode', '__pycache__',\r\n '.dsh-tmp', '.dsh-vision-router',\r\n '.agents', '.claude', '.devin', '.playwright-mcp', '.windsurf'\r\n]);\r\n\r\nconst DEFAULT_SKIP_FILES = new Set<string>([]);\r\n\r\nexport interface WalkOptions {\r\n skipDirs?: Set<string>;\r\n skipFiles?: Set<string>;\r\n ignoreGlobs?: string[];\r\n}\r\n\r\n/** Merge built-in skip lists with the project's `.codebase-chat.json` settings. */\r\nexport async function getWalkOptions(absProject: string): Promise<Required<WalkOptions>> {\r\n const cfg: ProjectConfig = await loadProjectConfig(absProject);\r\n return {\r\n skipDirs: new Set([...DEFAULT_SKIP_DIRS, ...(cfg.ignoreDirs ?? [])]),\r\n skipFiles: new Set([...DEFAULT_SKIP_FILES, ...(cfg.ignoreFiles ?? [])]),\r\n ignoreGlobs: cfg.ignoreGlobs ?? [],\r\n };\r\n}\r\n\r\nexport function projectHash(absProject: string): string {\r\n return createHash('sha256').update(absProject.toLowerCase()).digest('hex').slice(0, 16);\r\n}\r\n\r\nexport function resolveProjectPath(projectPath?: string): string {\r\n const raw = (projectPath ?? '').trim().replace(/['\"]/g, '');\r\n if (!raw) return process.cwd();\r\n if (isAbsolute(raw)) return resolve(raw);\r\n return resolve(process.cwd(), raw);\r\n}\r\n\r\nexport async function findProjectRoot(absProject: string): Promise<string> {\r\n try {\r\n const s = await stat(absProject);\r\n if (s.isDirectory()) return absProject;\r\n // If user points to a file, use its directory\r\n return resolve(absProject, '..');\r\n } catch {\r\n throw new Error(`Project path not found: ${absProject}`);\r\n }\r\n}\r\n\r\nexport function getCacheDir(): string {\r\n const base = process.env.CODEBASE_CACHE_DIR\r\n || process.env.LOCALAPPDATA\r\n || process.env.APPDATA\r\n || join(homedir(), '.cache');\r\n return join(base, 'dsh-codebase-chat-cache');\r\n}\r\n\r\nexport function cacheFilePath(absProject: string): string {\r\n return join(getCacheDir(), `${projectHash(absProject)}.json`);\r\n}\r\n\r\nexport function fileHash(stats: { mtimeMs: number; size: number }, firstBytes = ''): string {\r\n return createHash('sha256')\r\n .update(`${stats.mtimeMs}:${stats.size}:${firstBytes.slice(0, 512)}`)\r\n .digest('hex')\r\n .slice(0, 24);\r\n}\r\n\r\nexport async function* walkFiles(startDir: string, skipDirs = DEFAULT_SKIP_DIRS, skipFiles = DEFAULT_SKIP_FILES, ignoreGlobs: string[] = []): AsyncGenerator<string> {\r\n const queue: string[] = [startDir];\r\n while (queue.length) {\r\n const dir = queue.shift()!;\r\n let entries;\r\n try {\r\n entries = await readdir(dir, { withFileTypes: true });\r\n } catch {\r\n continue;\r\n }\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n const rel = relative(startDir, fullPath).split(sep).join('/');\r\n if (entry.isDirectory()) {\r\n if (!skipDirs.has(entry.name) && !matchesAnyGlob(rel, ignoreGlobs)) queue.push(fullPath);\r\n continue;\r\n }\r\n if (!entry.isFile()) continue;\r\n if (skipFiles.has(entry.name)) continue;\r\n if (matchesAnyGlob(rel, ignoreGlobs)) continue;\r\n const ext = extname(entry.name).toLowerCase();\r\n if (!SOURCE_EXTS.has(ext)) continue;\r\n yield fullPath;\r\n }\r\n }\r\n}\r\n\r\nexport async function safeReadText(filePath: string): Promise<string | undefined> {\r\n try {\r\n const text = await readFile(filePath, 'utf8');\r\n return text;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport async function buildTree(startDir: string, maxLines = 500, skipDirs = DEFAULT_SKIP_DIRS): Promise<string> {\r\n const lines: string[] = [];\r\n\r\n async function walk(dir: string, prefix = '') {\r\n if (lines.length >= maxLines) return;\r\n let entries;\r\n try {\r\n entries = await readdir(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n entries.sort((a, b) => (a.isDirectory() === b.isDirectory() ? a.name.localeCompare(b.name) : a.isDirectory() ? -1 : 1));\r\n for (const entry of entries) {\r\n if (lines.length >= maxLines) return;\r\n if (skipDirs.has(entry.name)) continue;\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n lines.push(`${prefix}${entry.name}/`);\r\n await walk(fullPath, `${prefix} `);\r\n } else {\r\n lines.push(`${prefix}${entry.name}`);\r\n }\r\n }\r\n }\r\n\r\n await walk(startDir);\r\n return lines.join('\\n');\r\n}\r\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type ConfigLang = 'fr' | 'en';\n\n/**\n * Per-project settings read from `.codebase-chat.json` at the project root.\n * Every field is optional — unset fields fall back to built-in defaults.\n */\nexport interface ProjectConfig {\n /** Default output language when the caller does not pass `lang` */\n lang?: ConfigLang;\n /** Default token budget for built contexts when the caller does not pass `maxTokens` */\n maxTokens?: number;\n /** Extra directory names skipped during indexing and analysis */\n ignoreDirs?: string[];\n /** Extra file names skipped during indexing and analysis */\n ignoreFiles?: string[];\n /** Glob patterns matched against project-relative paths (e.g. \"generated/**\") */\n ignoreGlobs?: string[];\n /** Extra paths that can never be patched (project-relative or absolute) */\n protectedPaths?: string[];\n}\n\nexport const CONFIG_FILE = '.codebase-chat.json';\n\nconst configCache = new Map<string, ProjectConfig>();\n\nfunction strArray(v: unknown): string[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out = v.filter((x): x is string => typeof x === 'string' && x.trim().length > 0);\n return out.length ? out.map(s => s.trim()) : undefined;\n}\n\nfunction sanitize(raw: unknown): ProjectConfig {\n if (raw == null || typeof raw !== 'object') return {};\n const o = raw as Record<string, unknown>;\n const cfg: ProjectConfig = {};\n if (o.lang === 'fr' || o.lang === 'en') cfg.lang = o.lang;\n if (typeof o.maxTokens === 'number' && Number.isFinite(o.maxTokens) && o.maxTokens > 0) {\n cfg.maxTokens = Math.floor(o.maxTokens);\n }\n const ignoreDirs = strArray(o.ignoreDirs); if (ignoreDirs) cfg.ignoreDirs = ignoreDirs;\n const ignoreFiles = strArray(o.ignoreFiles); if (ignoreFiles) cfg.ignoreFiles = ignoreFiles;\n const ignoreGlobs = strArray(o.ignoreGlobs); if (ignoreGlobs) cfg.ignoreGlobs = ignoreGlobs;\n const protectedPaths = strArray(o.protectedPaths); if (protectedPaths) cfg.protectedPaths = protectedPaths;\n return cfg;\n}\n\n/** Read `.codebase-chat.json` from the project root. Missing/invalid file → defaults. */\nexport async function loadProjectConfig(absProject: string): Promise<ProjectConfig> {\n const cached = configCache.get(absProject);\n if (cached) return cached;\n let cfg: ProjectConfig = {};\n try {\n cfg = sanitize(JSON.parse(await readFile(join(absProject, CONFIG_FILE), 'utf8')));\n } catch {\n // missing or malformed config file — keep defaults\n }\n configCache.set(absProject, cfg);\n return cfg;\n}\n\n/** Test/debug helper: drop the cached config for a project. */\nexport function clearConfigCache(absProject?: string): void {\n if (absProject == null) configCache.clear();\n else configCache.delete(absProject);\n}\n\nfunction escapeSegment(s: string): string {\n return s.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*').replace(/\\?/g, '[^/]');\n}\n\n/** Minimal glob → RegExp: `**` spans directories, `*` one segment, `?` one char. */\nexport function globToRegExp(glob: string): RegExp {\n const src = glob.replace(/\\\\/g, '/').split('**').map(escapeSegment).join('.*');\n return new RegExp(`^${src}$`);\n}\n\n/** Match a project-relative path (posix separators) against a list of globs. */\nexport function matchesAnyGlob(relPath: string, globs: string[] | undefined): boolean {\n if (!globs || globs.length === 0) return false;\n const rel = relPath.replace(/\\\\/g, '/');\n return globs.some(g => globToRegExp(g).test(rel));\n}\n","import type { CodeChunk, CodeIndex } from './types.js';\r\nimport { getEmbedding, cosineSimilarity } from './embeddings.js';\r\n\r\nconst STOP_WORDS = new Set([\r\n 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought', 'used', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'and', 'or', 'but', 'so', 'yet', 'a', 'an', 'this', 'that', 'these', 'those', 'it', 'its', 'he', 'she', 'they', 'them', 'their', 'we', 'us', 'our', 'you', 'your', 'i', 'me', 'my', 'le', 'la', 'les', 'un', 'une', 'des', 'du', 'de', 'et', 'ou', 'que', 'qui', 'quoi', 'dont', 'ce', 'cet', 'cette', 'ces', 'est', 'sont', 'etait', 'etaient', 'avoir', 'etre', 'faire', 'dans', 'pour', 'sur', 'avec', 'par', 'a', 'au', 'aux'\r\n]);\r\n\r\nfunction tokenizeQuery(text: string): string[] {\r\n return text\r\n .replace(/[^a-zA-Z0-9\\u00C0-\\u017F]+/g, ' ')\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter(Boolean)\r\n .filter(t => t.length > 2 && !STOP_WORDS.has(t));\r\n}\r\n\r\ninterface ScoredChunk extends CodeChunk {\r\n score: number;\r\n}\r\n\r\nfunction getChunkKey(chunk: CodeChunk): string {\r\n return `${chunk.relPath}:${chunk.startLine}:${chunk.endLine}`;\r\n}\r\n\r\nfunction lexicalScore(index: CodeIndex, query: string): Map<string, number> {\r\n const terms = tokenizeQuery(query);\r\n const scores = new Map<string, number>();\r\n\r\n if (terms.length === 0) return scores;\r\n\r\n const totalFiles = Math.max(Object.keys(index.files).length, 1);\r\n\r\n for (const term of terms) {\r\n const posting = index.terms[term];\r\n if (!posting) continue;\r\n // IDF: rare terms (few files) weigh more than ubiquitous ones.\r\n const df = Object.keys(posting).length;\r\n const idf = Math.log(1 + totalFiles / df);\r\n for (const [relPath, count] of Object.entries(posting)) {\r\n const file = index.files[relPath];\r\n if (!file) continue;\r\n for (const chunk of file.chunks) {\r\n const key = getChunkKey(chunk);\r\n const contentHit = chunk.content.toLowerCase().includes(term);\r\n const nameHit = chunk.name ? tokenizeQuery(chunk.name).includes(term) : false;\r\n // File-level term counts only matter for chunks that actually mention\r\n // the term — otherwise every chunk in a matched file inherits the score.\r\n if (!contentHit && !nameHit) continue;\r\n const bonus =\r\n (nameHit ? 4 : 0) +\r\n (chunk.kind === 'function' || chunk.kind === 'method' ? 1 : 0) +\r\n (contentHit ? 1 : 0);\r\n const prev = scores.get(key) ?? 0;\r\n scores.set(key, prev + count * idf + bonus);\r\n }\r\n }\r\n }\r\n\r\n return scores;\r\n}\r\n\r\n/**\r\n * Score all chunks against a query using the inverted index and, when available,\r\n * local sentence embeddings.\r\n */\r\nexport async function scoreChunks(index: CodeIndex, query: string, embed = false): Promise<ScoredChunk[]> {\r\n const lexScores = lexicalScore(index, query);\r\n\r\n // gather all chunks once\r\n const allChunks: CodeChunk[] = [];\r\n for (const file of Object.values(index.files)) {\r\n allChunks.push(...file.chunks);\r\n }\r\n\r\n let queryEmbedding: number[] | null = null;\r\n const hasEmbeddings = embed && allChunks.some(c => c.embedding && c.embedding.length > 0);\r\n\r\n if (hasEmbeddings) {\r\n try {\r\n queryEmbedding = await getEmbedding(query);\r\n } catch {\r\n queryEmbedding = null;\r\n }\r\n }\r\n\r\n const scored: ScoredChunk[] = [];\r\n for (const chunk of allChunks) {\r\n const key = getChunkKey(chunk);\r\n let score = lexScores.get(key) ?? 0;\r\n\r\n if (queryEmbedding && chunk.embedding && chunk.embedding.length === queryEmbedding.length) {\r\n const sim = cosineSimilarity(queryEmbedding, chunk.embedding);\r\n // semantic score is in [0, 1], scale it so it competes with lexical scores\r\n score += sim * 50;\r\n } else if (score === 0 && !hasEmbeddings) {\r\n // when no query terms matched and no embeddings, still return a fallback\r\n score = 0.1;\r\n }\r\n\r\n scored.push({ ...chunk, score });\r\n }\r\n\r\n return scored.sort((a, b) => b.score - a.score);\r\n}\r\n\r\n/**\r\n * Select chunks to fit within a token budget, keeping the most relevant first.\r\n */\r\nexport function selectChunks(scored: ScoredChunk[], maxTokens: number, maxChunkTokens = Infinity): { chunks: CodeChunk[]; tokens: number } {\r\n const result: CodeChunk[] = [];\r\n const covered = new Map<string, [number, number][]>();\r\n let used = 0;\r\n for (const chunk of scored) {\r\n if (chunk.tokens > maxChunkTokens) continue;\r\n if (used + chunk.tokens > maxTokens) continue;\r\n // Skip chunks fully covered by an already-selected chunk of the same file\r\n // (e.g. a method chunk inside a class chunk already picked).\r\n const ranges = covered.get(chunk.relPath) ?? [];\r\n const duplicated = ranges.some(([s, e]) => chunk.startLine >= s && chunk.endLine <= e);\r\n if (duplicated) continue;\r\n ranges.push([chunk.startLine, chunk.endLine]);\r\n covered.set(chunk.relPath, ranges);\r\n result.push(chunk);\r\n used += chunk.tokens;\r\n }\r\n return { chunks: result, tokens: used };\r\n}\r\n","import { execFile } from 'node:child_process';\nimport { sep } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst run = promisify(execFile);\n\nexport interface DiffScope {\n /** Project-relative paths (forward slashes) changed vs the base ref. */\n files: Set<string>;\n /** False when the project is not a git repo or git is unavailable. */\n ok: boolean;\n /** Why the scope could not be computed (when ok === false). */\n error?: string;\n}\n\nasync function git(absProject: string, args: string[]): Promise<string> {\n const { stdout } = await run('git', ['-C', absProject, ...args], { maxBuffer: 16 * 1024 * 1024 });\n return stdout;\n}\n\nfunction toRelList(output: string): string[] {\n return output\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean)\n .map(l => l.split(sep).join('/'));\n}\n\n/**\n * Files changed vs a git ref — committed diffs, staged/unstaged edits and\n * untracked files. Used to scope retrieval and audits to \"what changed\".\n */\nexport async function getChangedFiles(absProject: string, base: string): Promise<DiffScope> {\n try {\n const [tracked, untracked] = await Promise.all([\n // Working tree vs base — covers committed, staged and unstaged edits.\n git(absProject, ['diff', '--name-only', base, '--']),\n git(absProject, ['ls-files', '--others', '--exclude-standard']),\n ]);\n const files = new Set([...toRelList(tracked), ...toRelList(untracked)]);\n return { files, ok: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { files: new Set(), ok: false, error: msg.split('\\n')[0] };\n }\n}\n","import { basename, extname, join, relative, sep, posix as posixPath } from 'node:path';\r\nimport { readFile } from 'node:fs/promises';\r\nimport { findProjectRoot, getWalkOptions, resolveProjectPath, safeReadText, walkFiles } from './project.js';\r\n\r\nconst CODE_EXTS = new Set(['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx']);\r\nconst ENTRY_BASENAMES = new Set(['index', 'main', 'app', 'cli', 'server', 'bin', 'mod']);\r\nconst SKIP_EXTS = new Set(['.d.ts', '.test.ts', '.test.js', '.spec.ts', '.spec.js', '.config.js', '.config.ts', '.config.mjs']);\r\n\r\nexport interface ImportEdge { from: string; to: string; }\r\nexport interface Cycle { path: string[]; }\r\nexport interface UnusedExport { file: string; name: string; line: number; }\r\nexport interface CloneGroup { files: string[]; lines: number; preview: string; }\r\nexport interface Hotspot { file: string; name?: string; startLine: number; score: number; }\r\n\r\nexport interface HealthReport {\r\n projectPath: string;\r\n analyzedFiles: number;\r\n importEdges: number;\r\n cycles: Cycle[];\r\n unusedFiles: string[];\r\n unusedExports: UnusedExport[];\r\n duplicates: CloneGroup[];\r\n hotspots: Hotspot[];\r\n score: number;\r\n grade: 'A' | 'B' | 'C' | 'D' | 'E';\r\n}\r\n\r\nconst IMPORT_RE = /(?:import|export)\\s+(?:[\\w*{}\\s,]+\\s+from\\s+)?['\"]([^'\"]+)['\"]|require\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)|import\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\r\nconst EXPORT_RE = /export\\s+(?:async\\s+)?(?:function|class|const|let|var|interface|type|enum)\\s+([A-Za-z_$][\\w$]*)|export\\s*\\{\\s*([^}]+)\\}|export\\s+default\\b/g;\r\n\r\nfunction parseImports(text: string, relPath: string, known: Set<string>): string[] {\r\n const out: string[] = [];\r\n let m: RegExpExecArray | null;\r\n IMPORT_RE.lastIndex = 0;\r\n while ((m = IMPORT_RE.exec(text)) !== null) {\r\n const spec = m[1] ?? m[2] ?? m[3];\r\n if (!spec || !spec.startsWith('.')) continue;\r\n const base = posixPath.normalize(posixPath.join(posixPath.dirname(relPath), spec));\r\n // ESM imports often use a .js extension pointing at a .ts source file.\r\n const noExt = base.replace(/\\.(js|jsx|mjs|cjs|ts|tsx)$/, '');\r\n for (const cand of [base, `${noExt}.ts`, `${noExt}.tsx`, `${noExt}.js`, `${noExt}.jsx`, `${noExt}.mjs`, `${base}/index.ts`, `${base}/index.js`]) {\r\n if (known.has(cand)) { out.push(cand); break; }\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nexport function parseExports(text: string): { name: string; line: number }[] {\r\n const out: { name: string; line: number }[] = [];\r\n let m: RegExpExecArray | null;\r\n EXPORT_RE.lastIndex = 0;\r\n while ((m = EXPORT_RE.exec(text)) !== null) {\r\n const line = text.slice(0, m.index).split('\\n').length;\r\n if (m[1]) out.push({ name: m[1], line });\r\n else if (m[2]) {\r\n for (const part of m[2].split(',')) {\r\n const name = part.trim().split(/\\s+as\\s+/).pop()?.trim();\r\n if (name) out.push({ name, line });\r\n }\r\n } else out.push({ name: 'default', line });\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Detect cycle groups in the local import graph via Tarjan's SCC algorithm —\r\n * linear time, no combinatorial blow-up on dense graphs. Each reported\r\n * `Cycle.path` holds the members of one strongly connected component.\r\n */\r\nexport function findCycles(edges: ImportEdge[]): Cycle[] {\r\n const adj = new Map<string, string[]>();\r\n const nodes = new Set<string>();\r\n for (const e of edges) {\r\n nodes.add(e.from);\r\n nodes.add(e.to);\r\n if (!adj.has(e.from)) adj.set(e.from, []);\r\n adj.get(e.from)!.push(e.to);\r\n }\r\n\r\n const index = new Map<string, number>();\r\n const low = new Map<string, number>();\r\n const onStack = new Set<string>();\r\n const stack: string[] = [];\r\n const sccs: string[][] = [];\r\n let counter = 0;\r\n\r\n for (const root of nodes) {\r\n if (index.has(root)) continue;\r\n // Iterative DFS — no recursion limit on deep graphs.\r\n const work: [string, number][] = [[root, 0]];\r\n while (work.length) {\r\n const top = work[work.length - 1];\r\n const [v, ci] = top;\r\n if (ci === 0) {\r\n index.set(v, counter);\r\n low.set(v, counter);\r\n counter++;\r\n stack.push(v);\r\n onStack.add(v);\r\n }\r\n const children = adj.get(v) ?? [];\r\n if (ci < children.length) {\r\n top[1] = ci + 1;\r\n const w = children[ci];\r\n if (!index.has(w)) work.push([w, 0]);\r\n else if (onStack.has(w)) low.set(v, Math.min(low.get(v)!, index.get(w)!));\r\n } else {\r\n work.pop();\r\n if (work.length) {\r\n const parent = work[work.length - 1][0];\r\n low.set(parent, Math.min(low.get(parent)!, low.get(v)!));\r\n }\r\n if (low.get(v) === index.get(v)) {\r\n const scc: string[] = [];\r\n let w: string;\r\n do { w = stack.pop()!; onStack.delete(w); scc.push(w); } while (w !== v);\r\n // size > 1 = real cycle; size 1 only when the file imports itself\r\n if (scc.length > 1 || (adj.get(v) ?? []).includes(v)) sccs.push(scc);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return sccs\r\n .map(m => ({ path: m.sort() }))\r\n .sort((a, b) => b.path.length - a.path.length);\r\n}\r\n\r\nexport function looksLikeEntry(rel: string, pkg: Record<string, any>): boolean {\r\n const base = basename(rel).toLowerCase().replace(extname(rel), '');\r\n if (ENTRY_BASENAMES.has(base)) return true;\r\n // Test/spec files and tool configs are entry points by convention —\r\n // they are executed, not imported.\r\n if (/\\.(test|spec)\\.[cm]?[jt]sx?$/.test(rel) || rel.includes('__tests__/') || /^e2e[.-]/.test(basename(rel))) return true;\r\n if (/\\.(config|rc)\\.[cm]?[jt]s$/.test(rel)) return true;\r\n if (/^(pages|app|routes|api|bin|scripts)\\//.test(rel) || rel.includes('/pages/') || rel.includes('/routes/')) return true;\r\n const fields = [pkg?.main, pkg?.module, pkg?.bin, pkg?.exports?.['.']];\r\n for (const f of fields.flatMap(v => (typeof v === 'string' ? [v] : v ? Object.values(v) : []))) {\r\n if (typeof f === 'string' && rel.endsWith(f.replace(/^\\.\\//, ''))) return true;\r\n }\r\n return false;\r\n}\r\n\r\nfunction complexityOf(text: string): number {\r\n const matches = text.match(/\\b(if|else if|for|while|case|catch|&&|\\|\\||\\?)\\b|\\?\\./g);\r\n return 1 + (matches ? matches.length : 0);\r\n}\r\n\r\nconst WINDOW = 6;\r\nfunction findDuplicates(fileTexts: Map<string, string>): CloneGroup[] {\r\n const windows = new Map<string, { file: string; line: number }[]>();\r\n for (const [file, text] of fileTexts) {\r\n const lines = text.split('\\n').map(l => l.trim()).filter(l => l && !l.startsWith('//') && l !== '{' && l !== '}');\r\n for (let i = 0; i + WINDOW <= lines.length; i++) {\r\n const key = lines.slice(i, i + WINDOW).join('\\n');\r\n if (key.length < 60) continue;\r\n if (!windows.has(key)) windows.set(key, []);\r\n const arr = windows.get(key)!;\r\n if (!arr.some(w => w.file === file)) arr.push({ file, line: i + 1 });\r\n }\r\n }\r\n const groups = new Map<string, CloneGroup>();\r\n for (const [key, hits] of windows) {\r\n if (hits.length < 2) continue;\r\n const files = [...new Set(hits.map(h => h.file))].sort();\r\n const gk = files.join('|');\r\n const preview = key.split('\\n')[0].slice(0, 80);\r\n const g = groups.get(gk);\r\n if (g) g.lines += WINDOW;\r\n else groups.set(gk, { files, lines: WINDOW, preview });\r\n }\r\n return [...groups.values()].sort((a, b) => b.lines - a.lines).slice(0, 15);\r\n}\r\n\r\nexport interface AnalyzeOptions {\r\n /** Restrict *reported findings* to these project-relative paths (e.g. a diff\r\n * scope). The import graph and usage checks still run on the whole project\r\n * so cycles/uses crossing the scope boundary are detected. */\r\n files?: Set<string>;\r\n}\r\n\r\nexport interface ImportGraph {\r\n abs: string;\r\n codeFiles: string[];\r\n fileTexts: Map<string, string>;\r\n edges: ImportEdge[];\r\n inDegree: Map<string, number>;\r\n}\r\n\r\n/**\r\n * Walk the project once and build the local import graph (file → files it\r\n * imports). Shared by `analyzeProject` and `analyzeImpact` so both run the\r\n * same resolution rules.\r\n */\r\nexport async function collectImportGraph(projectPath: string): Promise<ImportGraph> {\r\n const abs = await findProjectRoot(resolveProjectPath(projectPath));\r\n const fileTexts = new Map<string, string>();\r\n const codeFiles: string[] = [];\r\n const walk = await getWalkOptions(abs);\r\n\r\n for await (const full of walkFiles(abs, walk.skipDirs, walk.skipFiles, walk.ignoreGlobs)) {\r\n const rel = relative(abs, full).split(sep).join('/');\r\n const ext = extname(rel).toLowerCase();\r\n if (!CODE_EXTS.has(ext) || SKIP_EXTS.has(ext) || rel.includes('.min.')) continue;\r\n const text = await safeReadText(full);\r\n if (!text) continue;\r\n codeFiles.push(rel);\r\n fileTexts.set(rel, text);\r\n }\r\n\r\n const known = new Set(codeFiles);\r\n const edges: ImportEdge[] = [];\r\n const inDegree = new Map<string, number>();\r\n for (const rel of codeFiles) {\r\n for (const to of parseImports(fileTexts.get(rel)!, rel, known)) {\r\n edges.push({ from: rel, to });\r\n inDegree.set(to, (inDegree.get(to) ?? 0) + 1);\r\n }\r\n }\r\n return { abs, codeFiles, fileTexts, edges, inDegree };\r\n}\r\n\r\nexport async function analyzeProject(projectPath: string, opts: AnalyzeOptions = {}): Promise<HealthReport> {\r\n const { abs, codeFiles, fileTexts, edges, inDegree } = await collectImportGraph(projectPath);\r\n const scope = opts.files;\r\n const scopedFiles = scope ? codeFiles.filter(f => scope.has(f)) : codeFiles;\r\n\r\n let pkg: Record<string, any> = {};\r\n try { pkg = JSON.parse(await readFile(join(abs, 'package.json'), 'utf8')); } catch {}\r\n\r\n // Full-graph cycles — when scoped, keep only cycles touching a changed file.\r\n const cycles = findCycles(edges)\r\n .filter(c => !scope || c.path.some(node => scope.has(node)));\r\n\r\n const unusedFiles = scopedFiles\r\n .filter(rel => !inDegree.has(rel) && !looksLikeEntry(rel, pkg))\r\n .sort();\r\n\r\n // Unused exports: name not imported and not referenced elsewhere.\r\n // One identifier pass per file (Set), then O(1) lookups — no per-export regex.\r\n const IDENT_RE = /[A-Za-z_$][\\w$]*/g;\r\n const identifiersByFile = new Map<string, Set<string>>();\r\n for (const [file, text] of fileTexts) {\r\n identifiersByFile.set(file, new Set(text.match(IDENT_RE) ?? []));\r\n }\r\n const unusedExports: UnusedExport[] = [];\r\n for (const rel of scopedFiles) {\r\n for (const exp of parseExports(fileTexts.get(rel)!)) {\r\n if (exp.name === 'default') continue;\r\n let used = false;\r\n for (const [otherFile, ids] of identifiersByFile) {\r\n if (otherFile === rel) continue;\r\n if (ids.has(exp.name)) { used = true; break; }\r\n }\r\n if (!used) unusedExports.push({ file: rel, name: exp.name, line: exp.line });\r\n }\r\n }\r\n\r\n // Duplicates across the whole project, but when scoped only report groups\r\n // that include at least one changed file.\r\n const duplicates = findDuplicates(fileTexts)\r\n .filter(g => !scope || g.files.some(f => scope.has(f)));\r\n\r\n const hotspots: Hotspot[] = [];\r\n for (const rel of scopedFiles) {\r\n const score = complexityOf(fileTexts.get(rel)!);\r\n if (score >= 12) hotspots.push({ file: rel, startLine: 1, score });\r\n }\r\n hotspots.sort((a, b) => b.score - a.score);\r\n\r\n const codeLines = scopedFiles.reduce((s, f) => s + fileTexts.get(f)!.split('\\n').length, 0);\r\n const dupLines = duplicates.reduce((s, g) => s + g.lines, 0);\r\n // Cycle penalty scales with how many files are trapped in cycle groups.\r\n const cyclesPenalty = cycles.reduce((s, c) => s + c.path.length, 0) * 2;\r\n const penalties =\r\n cyclesPenalty +\r\n unusedFiles.length * 2 +\r\n Math.min(unusedExports.length, 20) * 1 +\r\n Math.round((dupLines / Math.max(codeLines, 1)) * 100) +\r\n Math.min(hotspots.length, 15) * 2;\r\n const score = Math.max(0, Math.min(100, 100 - penalties));\r\n const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 65 ? 'C' : score >= 50 ? 'D' : 'E';\r\n\r\n return {\r\n projectPath: abs,\r\n analyzedFiles: scopedFiles.length,\r\n importEdges: edges.length,\r\n cycles,\r\n unusedFiles,\r\n unusedExports,\r\n duplicates,\r\n hotspots,\r\n score,\r\n grade,\r\n };\r\n}\r\n\r\nexport function formatHealthReport(r: HealthReport, lang: 'fr' | 'en' = 'fr'): string {\r\n const t = lang === 'en'\r\n ? {\r\n title: 'STATIC ANALYSIS', files: 'files analyzed', edges: 'local imports',\r\n cycles: 'Circular dependencies', none: 'none',\r\n unusedFiles: 'Unused files (candidates)', unusedExports: 'Unused exports (candidates)',\r\n dupes: 'Duplicate code blocks', hotspots: 'Complexity hotspots',\r\n score: 'Health score', noteUnused: 'candidates — entry points and framework conventions excluded',\r\n }\r\n : {\r\n title: 'ANALYSE STATIQUE', files: 'fichiers analysés', edges: 'imports locaux',\r\n cycles: 'Dépendances circulaires', none: 'aucune',\r\n unusedFiles: 'Fichiers inutilisés (candidats)', unusedExports: 'Exports inutilisés (candidats)',\r\n dupes: 'Blocs de code dupliqués', hotspots: 'Hotspots de complexité',\r\n score: 'Score de santé', noteUnused: 'candidats — points d’entrée et conventions exclus',\r\n };\r\n\r\n const out: string[] = [];\r\n out.push(`== ${t.title} — ${basename(r.projectPath)} ==`);\r\n out.push(`${t.score}: ${r.score}/100 (${r.grade}) · ${r.analyzedFiles} ${t.files} · ${r.importEdges} ${t.edges}`);\r\n out.push('');\r\n\r\n out.push(`● ${t.cycles} (${r.cycles.length})`);\r\n for (const c of r.cycles.slice(0, 10)) out.push(` ${formatCycle(c)}`);\r\n if (r.cycles.length === 0) out.push(` ${t.none}`);\r\n out.push('');\r\n\r\n out.push(`● ${t.unusedFiles} (${r.unusedFiles.length}) — ${t.noteUnused}`);\r\n for (const f of r.unusedFiles.slice(0, 15)) out.push(` ${f}`);\r\n out.push('');\r\n\r\n out.push(`● ${t.unusedExports} (${r.unusedExports.length})`);\r\n for (const e of r.unusedExports.slice(0, 15)) out.push(` ${e.file}:${e.line} — ${e.name}`);\r\n out.push('');\r\n\r\n out.push(`● ${t.dupes} (${r.duplicates.length})`);\r\n for (const d of r.duplicates.slice(0, 8)) out.push(` ${d.lines} lines × ${d.files.length} files — ${d.files.join(', ')}`);\r\n out.push('');\r\n\r\n out.push(`● ${t.hotspots} (${r.hotspots.length})`);\r\n for (const h of r.hotspots.slice(0, 10)) out.push(` ${h.file} — score ${h.score}`);\r\n return out.join('\\n');\r\n}\r\n\r\n/** Small SCCs render as a closed loop; large ones as a file list. */\r\nfunction formatCycle(c: Cycle, md = false): string {\r\n const q = (s: string) => (md ? `\\`${s}\\`` : s);\r\n if (c.path.length <= 4) return c.path.map(q).join(' → ') + ' → ' + q(c.path[0]);\r\n const shown = c.path.slice(0, 4).map(q).join(', ');\r\n return `${c.path.length} files: ${shown}, …`;\r\n}\r\n\r\nconst GRADE_ICON: Record<HealthReport['grade'], string> = { A: '🟢', B: '🔵', C: '🟡', D: '🟠', E: '🔴' };\r\n\r\nfunction scoreBar(score: number): string {\r\n const filled = Math.round(score / 10);\r\n return '█'.repeat(filled) + '░'.repeat(10 - filled);\r\n}\r\n\r\nexport function formatHealthReportMd(r: HealthReport, lang: 'fr' | 'en' = 'fr'): string {\r\n const t = lang === 'en'\r\n ? {\r\n title: 'Static analysis', files: 'files analyzed', edges: 'local imports',\r\n cycles: 'Circular dependencies', none: 'None',\r\n unusedFiles: 'Unused files (candidates)', unusedExports: 'Unused exports (candidates)',\r\n dupes: 'Duplicate code blocks', hotspots: 'Complexity hotspots',\r\n score: 'Health score', noteUnused: '_candidates — entry points and framework conventions excluded_',\r\n colFile: 'File', colSymbol: 'Symbol', colSize: 'Size', colFiles: 'Files', colScore: 'Score',\r\n more: (n: number) => `_…and ${n} more_`,\r\n }\r\n : {\r\n title: 'Analyse statique', files: 'fichiers analysés', edges: 'imports locaux',\r\n cycles: 'Dépendances circulaires', none: 'Aucune',\r\n unusedFiles: 'Fichiers inutilisés (candidats)', unusedExports: 'Exports inutilisés (candidats)',\r\n dupes: 'Blocs de code dupliqués', hotspots: 'Hotspots de complexité',\r\n score: 'Score de santé', noteUnused: '_candidats — points d’entrée et conventions exclus_',\r\n colFile: 'Fichier', colSymbol: 'Symbole', colSize: 'Taille', colFiles: 'Fichiers', colScore: 'Score',\r\n more: (n: number) => `_…et ${n} autres_`,\r\n };\r\n\r\n const out: string[] = [];\r\n out.push(`## ${GRADE_ICON[r.grade]} ${t.title} — \\`${basename(r.projectPath)}\\``);\r\n out.push('');\r\n out.push(`**${t.score} : ${scoreBar(r.score)} ${r.score}/100 (${r.grade})** · ${r.analyzedFiles} ${t.files} · ${r.importEdges} ${t.edges}`);\r\n out.push('');\r\n\r\n out.push(`### ${t.cycles} — ${r.cycles.length}`);\r\n if (r.cycles.length === 0) out.push(t.none);\r\n else for (const c of r.cycles.slice(0, 10)) out.push(`- ${formatCycle(c, true)}`);\r\n if (r.cycles.length > 10) out.push(t.more(r.cycles.length - 10));\r\n out.push('');\r\n\r\n out.push(`### ${t.unusedFiles} — ${r.unusedFiles.length}`);\r\n out.push(t.noteUnused);\r\n if (r.unusedFiles.length) {\r\n out.push('', `| ${t.colFile} |`, '|---|---|');\r\n for (const f of r.unusedFiles.slice(0, 15)) out.push(`| \\`${f}\\` |`);\r\n if (r.unusedFiles.length > 15) out.push(`| ${t.more(r.unusedFiles.length - 15)} |`);\r\n }\r\n out.push('');\r\n\r\n out.push(`### ${t.unusedExports} — ${r.unusedExports.length}`);\r\n if (r.unusedExports.length) {\r\n out.push('', `| ${t.colFile} | ${t.colSymbol} |`, '|---|---|');\r\n for (const e of r.unusedExports.slice(0, 15)) out.push(`| \\`${e.file}:${e.line}\\` | \\`${e.name}\\` |`);\r\n if (r.unusedExports.length > 15) out.push(`| ${t.more(r.unusedExports.length - 15)} | |`);\r\n } else out.push(t.none);\r\n out.push('');\r\n\r\n out.push(`### ${t.dupes} — ${r.duplicates.length}`);\r\n if (r.duplicates.length) {\r\n out.push('', `| ${t.colSize} | ${t.colFiles} |`, '|---|---|');\r\n for (const d of r.duplicates.slice(0, 8)) {\r\n out.push(`| ${d.lines} × ${d.files.length} | ${d.files.map(f => `\\`${f}\\``).join(', ')} |`);\r\n }\r\n if (r.duplicates.length > 8) out.push(`| ${t.more(r.duplicates.length - 8)} | |`);\r\n } else out.push(t.none);\r\n out.push('');\r\n\r\n out.push(`### ${t.hotspots} — ${r.hotspots.length}`);\r\n if (r.hotspots.length) {\r\n out.push('', `| ${t.colFile} | ${t.colScore} |`, '|---|---|');\r\n for (const h of r.hotspots.slice(0, 10)) out.push(`| \\`${h.file}\\` | **${h.score}** |`);\r\n if (r.hotspots.length > 10) out.push(`| ${t.more(r.hotspots.length - 10)} | |`);\r\n } else out.push(t.none);\r\n\r\n return out.join('\\n');\r\n}\r\n","import { basename } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { collectImportGraph, looksLikeEntry, parseExports } from './analysis.js';\n\nexport interface ImpactDependent { file: string; depth: number; }\n\nexport interface ImpactReport {\n projectPath: string;\n query: string;\n target: string;\n exportedSymbols: { name: string; line: number }[];\n dependents: ImpactDependent[];\n directCount: number;\n totalFiles: number;\n /** Share of the project's code files that transitively depend on the target. */\n percent: number;\n inCycle: boolean;\n isEntry: boolean;\n risk: 'low' | 'medium' | 'high';\n}\n\nexport type ImpactResult =\n | { ok: true; report: ImpactReport }\n | { ok: false; query: string; candidates: string[] };\n\n/** Rank a candidate path against the query — lower is better, -1 = no match. */\nfunction matchRank(rel: string, q: string): number {\n if (rel === q) return 0;\n if (rel.endsWith(`/${q}`)) return 1;\n if (basename(rel) === q) return 2;\n if (rel.toLowerCase().includes(q.toLowerCase())) return 3;\n return -1;\n}\n\nfunction resolveTarget(codeFiles: string[], query: string): { target?: string; candidates: string[] } {\n const q = query.trim().replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n if (!q) return { candidates: [] };\n const ranked = codeFiles\n .map(f => ({ f, r: matchRank(f, q) }))\n .filter(m => m.r >= 0)\n .sort((a, b) => a.r - b.r || a.f.length - b.f.length);\n if (!ranked.length) return { candidates: [] };\n const best = ranked.filter(m => m.r === ranked[0].r);\n if (best.length === 1) return { target: best[0].f, candidates: [] };\n return { candidates: best.slice(0, 12).map(m => m.f) };\n}\n\n/**\n * Blast-radius analysis: which files break if `query` changes. Reverse BFS on\n * the local import graph — deterministic, no LLM.\n */\nexport async function analyzeImpact(projectPath: string, query: string): Promise<ImpactResult> {\n const g = await collectImportGraph(projectPath);\n const { target, candidates } = resolveTarget(g.codeFiles, query);\n if (!target) return { ok: false, query, candidates };\n\n const rev = new Map<string, string[]>();\n for (const e of g.edges) {\n if (!rev.has(e.to)) rev.set(e.to, []);\n rev.get(e.to)!.push(e.from);\n }\n\n // Reverse BFS — a path coming back to the target reveals a cycle.\n let inCycle = false;\n const queue: string[] = [target];\n let head = 0;\n const dist = new Map<string, number>([[target, 0]]);\n while (head < queue.length) {\n const node = queue[head++];\n const d = dist.get(node)!;\n for (const up of rev.get(node) ?? []) {\n if (up === target) { inCycle = true; continue; }\n if (dist.has(up)) continue;\n dist.set(up, d + 1);\n queue.push(up);\n }\n }\n dist.delete(target);\n\n const dependents = [...dist.entries()]\n .map(([file, d]) => ({ file, depth: d }))\n .sort((a, b) => a.depth - b.depth || a.file.localeCompare(b.file));\n const directCount = dependents.filter(d => d.depth === 1).length;\n\n let pkg: Record<string, any> = {};\n try { pkg = JSON.parse(await readFile(join(g.abs, 'package.json'), 'utf8')); } catch {}\n const isEntry = looksLikeEntry(target, pkg);\n\n const total = dependents.length;\n const percent = g.codeFiles.length ? total / g.codeFiles.length : 0;\n const risk: ImpactReport['risk'] =\n inCycle || percent >= 0.25 || total >= 25 ? 'high'\n : percent >= 0.05 || total >= 5 ? 'medium'\n : 'low';\n\n return {\n ok: true,\n report: {\n projectPath: g.abs,\n query,\n target,\n exportedSymbols: parseExports(g.fileTexts.get(target) ?? ''),\n dependents,\n directCount,\n totalFiles: g.codeFiles.length,\n percent,\n inCycle,\n isEntry,\n risk,\n },\n };\n}\n\nconst RISK_ICON = { low: '🟢', medium: '🟡', high: '🔴' } as const;\n\nexport function formatImpactReport(r: ImpactReport, lang: 'fr' | 'en' = 'fr'): string {\n const t = lang === 'en'\n ? {\n title: 'IMPACT ANALYSIS', target: 'Target', exports: 'Exported symbols',\n direct: 'Direct dependents', total: 'Total blast radius', files: 'code files',\n inCycle: 'part of a dependency cycle', entry: 'entry point',\n risk: 'Risk', low: 'LOW', medium: 'MEDIUM', high: 'HIGH',\n depth: 'depth', none: 'none — nothing imports this file', more: (n: number) => `…and ${n} more`,\n }\n : {\n title: 'ANALYSE D’IMPACT', target: 'Cible', exports: 'Symboles exportés',\n direct: 'Dépendants directs', total: 'Rayon d’impact total', files: 'fichiers de code',\n inCycle: 'dans un cycle de dépendances', entry: 'point d’entrée',\n risk: 'Risque', low: 'FAIBLE', medium: 'MOYEN', high: 'ÉLEVÉ',\n depth: 'profondeur', none: 'aucun — rien n’importe ce fichier', more: (n: number) => `…et ${n} autres`,\n };\n\n const tags = [r.isEntry ? t.entry : '', r.inCycle ? t.inCycle : ''].filter(Boolean).join(' · ');\n const out: string[] = [];\n out.push(`== ${t.title} — ${basename(r.projectPath)} ==`);\n out.push(`${t.target}: ${r.target}${tags ? ` (${tags})` : ''}`);\n out.push(`${t.exports}: ${r.exportedSymbols.length ? r.exportedSymbols.map(s => s.name).join(', ') : '—'}`);\n out.push(`${t.direct}: ${r.directCount} · ${t.total}: ${r.dependents.length} / ${r.totalFiles} ${t.files} (${Math.round(r.percent * 100)}%)`);\n out.push(`${t.risk}: ${t[riskKey(r.risk)]}`);\n out.push('');\n if (!r.dependents.length) {\n out.push(` ${t.none}`);\n return out.join('\\n');\n }\n const byDepth = new Map<number, string[]>();\n for (const d of r.dependents) {\n if (!byDepth.has(d.depth)) byDepth.set(d.depth, []);\n byDepth.get(d.depth)!.push(d.file);\n }\n for (const [d, files] of [...byDepth.entries()].sort((a, b) => a[0] - b[0])) {\n out.push(` ${t.depth} ${d} (${files.length}):`);\n for (const f of files.slice(0, 12)) out.push(` ${f}`);\n if (files.length > 12) out.push(` ${t.more(files.length - 12)}`);\n }\n return out.join('\\n');\n}\n\nfunction riskKey(r: ImpactReport['risk']): 'low' | 'medium' | 'high' { return r; }\n\nexport function formatImpactReportMd(r: ImpactReport, lang: 'fr' | 'en' = 'fr'): string {\n const t = lang === 'en'\n ? {\n title: 'Impact analysis', target: 'Target', exports: 'Exported symbols',\n direct: 'Direct dependents', total: 'Total blast radius', files: 'code files',\n inCycle: 'part of a dependency cycle', entry: 'entry point',\n risk: 'Risk', low: 'LOW', medium: 'MEDIUM', high: 'HIGH',\n colDepth: 'Depth', colFile: 'File', none: '_None — nothing imports this file._',\n more: (n: number) => `_…and ${n} more_`,\n }\n : {\n title: 'Analyse d’impact', target: 'Cible', exports: 'Symboles exportés',\n direct: 'Dépendants directs', total: 'Rayon d’impact total', files: 'fichiers de code',\n inCycle: 'dans un cycle de dépendances', entry: 'point d’entrée',\n risk: 'Risque', low: 'FAIBLE', medium: 'MOYEN', high: 'ÉLEVÉ',\n colDepth: 'Profondeur', colFile: 'Fichier', none: '_Aucun — rien n’importe ce fichier._',\n more: (n: number) => `_…et ${n} autres_`,\n };\n\n const tags = [r.isEntry ? t.entry : '', r.inCycle ? t.inCycle : ''].filter(Boolean).join(' · ');\n const out: string[] = [];\n out.push(`## ${RISK_ICON[r.risk]} ${t.title} — \\`${basename(r.projectPath)}\\``);\n out.push('');\n out.push(`**${t.target} : \\`${r.target}\\`**${tags ? ` — _${tags}_` : ''}`);\n out.push('');\n out.push(`- **${t.exports}** : ${r.exportedSymbols.length ? r.exportedSymbols.map(s => `\\`${s.name}\\``).join(', ') : '—'}`);\n out.push(`- **${t.direct}** : ${r.directCount} · **${t.total}** : **${r.dependents.length}** / ${r.totalFiles} ${t.files} (**${Math.round(r.percent * 100)}%**)`);\n out.push(`- **${t.risk}** : **${t[riskKey(r.risk)]}**`);\n out.push('');\n if (!r.dependents.length) {\n out.push(t.none);\n return out.join('\\n');\n }\n out.push(`| ${t.colDepth} | ${t.colFile} |`, '|---|---|');\n for (const d of r.dependents.slice(0, 30)) out.push(`| ${d.depth} | \\`${d.file}\\` |`);\n if (r.dependents.length > 30) out.push(`| | ${t.more(r.dependents.length - 30)} |`);\n return out.join('\\n');\n}\n"],"mappings":"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","names":["sep","join","readFile","stat","dirname","join","relative","sep","start","require","t","readFile","join","join","join","readFile","t","readFile","dirname","sep","relative","stat","join","STOP_WORDS","t","sep","join","extname","join","relative","sep","readFile","extname","relative","sep","readFile","join","score","t","basename","readFile","join","basename","readFile","join","t","basename","sep"]}