dsh-codebase-chat 0.25.5 → 0.25.6

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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","../src/prompts.ts","../src/local-llm.ts"],"sourcesContent":["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, walk.skipFiles, walk.ignoreGlobs);\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 'target', 'bin', 'obj', 'vendor', '.venv', 'venv', '__pycache__',\r\n '.npm-cache', '.parcel-cache', '.gradle', '.mypy_cache', '.pytest_cache',\r\n 'android', 'ios', 'e2e-shots', 'playstore_screenshots',\r\n '.cursor', '.idea', '.memsearch', '.vscode',\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) && !skipDirs.has(rel) && !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, skipFiles = DEFAULT_SKIP_FILES, ignoreGlobs: string[] = []): 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 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) || skipDirs.has(rel) || matchesAnyGlob(rel, ignoreGlobs)) continue;\r\n lines.push(`${prefix}${entry.name}/`);\r\n await walk(fullPath, `${prefix} `);\r\n } else {\r\n if (skipFiles.has(entry.name) || matchesAnyGlob(rel, ignoreGlobs)) continue;\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. Globs without `/` match the basename at any depth (gitignore-style). */\nexport function matchesAnyGlob(relPath: string, globs: string[] | undefined): boolean {\n if (!globs || globs.length === 0) return false;\n const rel = relPath.replace(/\\\\/g, '/');\n const base = rel.split('/').pop() ?? rel;\n return globs.some(g => {\n const re = globToRegExp(g);\n return re.test(rel) || (!g.includes('/') && re.test(base));\n });\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 if (r.analyzedFiles === 0) {\r\n out.push(lang === 'en'\r\n ? 'No code files detected in this project — check the path or your .codebase-chat.json ignore rules.'\r\n : 'Aucun fichier de code détecté dans ce projet — vérifie le chemin ou les règles ignore de .codebase-chat.json.');\r\n return out.join('\\n');\r\n }\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 if (r.analyzedFiles === 0) {\r\n out.push(lang === 'en'\r\n ? '_No code files detected in this project — check the path or your `.codebase-chat.json` ignore rules._'\r\n : '_Aucun fichier de code détecté dans ce projet — vérifie le chemin ou les règles ignore de `.codebase-chat.json`._');\r\n return out.join('\\n');\r\n }\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","import { readFileSync } from 'node:fs';\nimport figlet from 'figlet';\n\nlet cachedVersion: string | undefined;\nfunction promptVersion(): string {\n if (!cachedVersion) {\n try {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { version?: string };\n cachedVersion = pkg.version ?? '0.0.0';\n } catch {\n cachedVersion = '0.0.0';\n }\n }\n return cachedVersion;\n}\n\nexport interface ToolPromptOptions {\n context: string;\n projectName: string;\n lang?: string;\n style?: string;\n query?: string;\n focus?: string;\n filePath?: string;\n description?: string;\n crea?: boolean;\n creaTheme?: string;\n}\n\nexport function citationInstruction(lang = \"fr\"): string {\n const isEn = lang === \"en\";\n return `${isEn ? \"## Evidence & Scoring (mandatory)\" : \"## Sources & Scoring (obligatoire)\"}\\n- ${isEn ? \"Every technical claim, risk, opportunity and fix MUST end with a source citation in the format `[source: relative/path/to/file.ts:line]` (e.g. `[source: src/App.tsx:42]`).\" : \"Chaque affirmation technique, risque, opportunité et correctif DOIT se terminer par une citation source au format `[source: chemin/relatif/vers/fichier.ts:ligne]` (ex. `[source: src/App.tsx:42]`).\"}\\n- ${isEn ? \"Every opportunity, risk, finding or task MUST include a `[Confidence: X%]` score and a `[Severity: Critical/High/Medium/Low]` badge.\" : \"Chaque opportunité, risque, constat ou tâche DOIT inclure un score `[Confiance : X%]` et un badge `[Sévérité : Critique/Élevée/Moyenne/Faible]`.\"}\\n- ${isEn ? \"Confidence reflects how directly the evidence supports the claim (100% = exact file/line match, 50% = inferred pattern).\" : \"La confiance reflète à quel point l'evidence supporte directement l'affirmation (100% = correspondance exacte fichier/ligne, 50% = pattern inféré).\"}\\n- ${isEn ? \"Do not invent citations. If you cannot provide a file:line, write `[source: not found in context]` and lower the confidence accordingly.\" : \"Ne pas inventer de citations. Si vous ne pouvez pas donner fichier:ligne, écrivez `[source: non trouvé dans le contexte]` et baissez la confiance en conséquence.\"}\\n`;\n}\n\nexport function withCitations(prompt: string, lang = \"fr\"): string {\n return `${prompt}\\n\\n${citationInstruction(lang)}`;\n}\n\nexport function langInstruction(lang = \"fr\"): string {\n if (lang === \"en\") {\n return \"IMPORTANT: This whole prompt is in French for context, but the user requested English. Your ENTIRE response MUST be written in English. Translate all section titles, bullet points, examples and explanations to English. Do not output any French words except quoted code or file paths.\";\n }\n return \"IMPORTANT: Reponds obligatoirement en francais. Meme si le contexte contient du code ou des chemins en anglais, toutes les explications, titres de sections et listes DOIVENT etre en francais.\";\n}\n\nexport function normalizeLabels(prompt: string, lang: string): string {\n if (lang !== \"en\") return prompt;\n const map = {\n \"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language).\",\n \"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language)\",\n \"Conclus par la phrase-clé \\\"Fait avec passion par shinzarou-eng\\\" dans la langue de l'utilisateur.\": \"Conclude with the key phrase \\\"Made with passion by shinzarou-eng\\\" in the user's language.\",\n \"Conclus par la phrase-clé \\\"Fait avec passion par shinzarou-eng\\\" dans la langue de l'utilisateur\": \"Conclude with the key phrase \\\"Made with passion by shinzarou-eng\\\" in the user's language\",\n \"Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language)\",\n \"Fait avec passion par shinzarou-eng\": \"Made with passion by shinzarou-eng\",\n \"Justification\": \"Rationale\",\n \"Avant :\": \"Before:\",\n \"Avant:\": \"Before:\",\n \"Après :\": \"After:\",\n \"Après:\": \"After:\",\n \"Contraintes produit IDENTIFIEES\": \"IDENTIFIED PRODUCT CONSTRAINTS\",\n \"Contraintes produit identifiees\": \"Identified product constraints\",\n \"CONTRAINTES PRODUIT IDENTIFIEES\": \"IDENTIFIED PRODUCT CONSTRAINTS\",\n \"Ton et style\": \"Tone and style\",\n \"Sections obligatoires\": \"Required sections\",\n \"CHECKLIST FINALE\": \"FINAL CHECKLIST\",\n \"Vue d'ensemble\": \"Overview\",\n \"Fondations (Sécurité / Stabilité)\": \"Foundations (Security / Stability)\",\n \"Amélioration (Refacto / Qualité)\": \"Improvement (Refactor / Quality)\",\n \"Optimisation (Perf / Tests)\": \"Optimization (Performance / Tests)\",\n \"Différenciation (UX / Produit)\": \"Differentiation (UX / Product)\",\n \"Fichier(s) concerné(s)\": \"Concerned file(s)\",\n \"Difficulté\": \"Difficulty\",\n \"Livrable\": \"Deliverable\",\n \"Priorité\": \"Priority\",\n \"Tâche\": \"Task\",\n \"Fichier non trouve\": \"File not found\",\n \"Rapport généré par\": \"Report by\",\n \"Conçu pour DeepSeek Harness. Extensible à tout agent ou IDE Node.js.\": \"Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.\",\n \"Analyse de Codebase\": \"Codebase Analysis\",\n \"Projet\": \"Project\",\n \"Arborescence\": \"File tree\",\n \"Aucune contrainte explicite documentee.\": \"No explicit constraints documented.\"\n };\n let out = prompt;\n for (const [fr, en] of Object.entries(map)) {\n out = out.replaceAll(fr, en);\n }\n return out;\n}\n\nexport function creaFooter(_projectName: string, theme: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const t = theme || (isEn ? \"a creative proposal adapted\" : \"une proposition creative adaptee\");\n if (isEn) {\n return `\\n\\n---\\n\\nMade with passion by shinzarou-eng: from this analysis, generate a creative thing on the theme \"${t}\" (slogan, feature name, tagline, visual concept, marketing one-liner, or feature idea). Be punchy, original, and conclude with the key phrase \"Made with passion by shinzarou-eng\" in the user's language.`;\n }\n return `\\n\\n---\\n\\nFait avec passion par shinzarou-eng : à partir de cette analyse, génère un truc créatif sur le thème \"${t}\" (slogan, nom de feature, tagline, concept visuel, one-liner marketing, ou idée de fonctionnalité). Sois percutant, original, et conclus par la phrase-clé \"Fait avec passion par shinzarou-eng\" dans la langue de l'utilisateur.`;\n}\n\nexport function buildChatPrompt(question: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Codebase Chat\" : \"Codebase Chat\", isEn ? \"QUESTION / ANSWER\" : \"QUESTION / RÉPONSE\");\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a codebase expert assistant. Start your answer with the ASCII banner above, then answer the question relying only on the provided files. Cite relevant files and lines.` : `Tu es un assistant expert en codebase. Commence ta réponse par la bannière ASCII ci-dessus, puis réponds à la question en t'appuyant uniquement sur les fichiers fournis. Cite les fichiers et lignes pertinents.`}\\n\\n${isEn ? \"Question\" : \"Question\"} : ${question}\\n\\n${isEn ? \"Answer\" : \"Réponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildSearchPrompt(query: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Codebase Search\" : \"Codebase Search\", `${isEn ? \"SEARCH\" : \"RECHERCHE\"} : ${query}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a codebase search engine. Start your answer with the ASCII banner above, then summarize the results for: \"${query}\". Cite relevant paths and snippets as a prioritized list.` : `Tu es un moteur de recherche codebase. Commence ta réponse par la bannière ASCII ci-dessus, puis résume les résultats pour : \"${query}\". Cite les chemins et extraits pertinents sous forme de liste priorisée.`}\\n\\n${isEn ? \"Answer\" : \"Réponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildExplainPrompt(target: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Explanation\" : \"Explication\", `${isEn ? \"FILE OR SYMBOL\" : \"FICHIER OU SYMBOLE\"} : ${target}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `Explain how \"${target}\" works in this project. Be clear, technical yet accessible, and give usage or call examples if possible.` : `Explique le fonctionnement de \"${target}\" dans ce projet. Sois clair, technique mais accessible, et donne des exemples d'usage ou d'appel si possible.`}\\n\\n${isEn ? \"Answer\" : \"Reponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildRefactorPrompt(filePath: string, description: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const desc = description || (isEn ? \"improve the file\" : \"ameliorer le fichier\");\n const banner = bannerInstruction(projectName, isEn ? \"Refactor\" : \"Refactor\", `${isEn ? \"FILE\" : \"FICHIER\"} : ${filePath}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a senior architect. Refactor the file \"${filePath}\" according to the following request: ${desc}\\n\\nProvide production-ready code, explain the changes, and indicate any regressions to check.` : `Tu es un architecte senior. Refactorise le fichier \"${filePath}\" selon la demande suivante : ${desc}\\n\\nPropose du code pret a l'emploi, explique les changements, et indique les eventuelles regressions a verifier.`}\\n\\n${isEn ? \"Answer\" : \"Reponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildCreaPrompt(theme: string, context: string, projectName: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const t = theme || (isEn ? \"a creative proposal inspired by this project\" : \"une proposition creative inspiree par ce projet\");\n const banner = bannerInstruction(projectName, isEn ? \"Crea / Ideation\" : \"Créa / Ideation\", `${isEn ? \"THEME\" : \"THÈME\"} : ${t}`);\n const base = isEn\n ? `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a creative director / growth hacker. Analyze this codebase and generate a creative and marketing proposal for the project \"${projectName}\" on the theme \"${t}\". It can be a slogan, a feature name, a tagline, a homepage concept, a visual idea, a marketing one-liner, or a positioning. Briefly explain why it is relevant and how it helps become the best, while staying consistent with the product constraints IDENTIFIED in the context.\\n\\nConclude with: Made with passion by shinzarou-eng (in the user's language).`\n : `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un directeur creatif / growth hacker. Analyse ce codebase et génère une proposition créative et marketing pour le projet \"${projectName}\" sur le thème \"${t}\". Peut être un slogan, un nom de feature, une tagline, un concept de page d'accueil, une idée visuelle, un one-liner marketing, ou un positionnement. Explique brièvement pourquoi c'est pertinent et comment ça aide à devenir le meilleur, en restant cohérent avec les contraintes du projet IDENTIFIEES dans le contexte.\\n\\nConclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).`;\n return withCitations(base, lang);\n}\n\nexport function styleInstruction(style = \"ouf\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const heading = isEn ? \"## Writing Style (mandatory)\" : \"## Style de rédaction (obligatoire)\";\n const tones: Record<string, string> = isEn ? {\n ouf: \"'WOW' tone: the most beautiful, dense and punchy technical report the user has ever seen. Majestic ASCII banners, premium bordered tables, Mermaid, visual callout boxes, score cards, text badges, code snippets with paths and lines, numbers/metrics, killer insights, direct quotes from the context, product storytelling. ZERO empty phrases. Each section must be rich, stylish and actionable. Action verbs, justified superlatives. Give the reader chills.\",\n punchy: \"PUNCHY / DENSE tone: short and punchy sentences, every line brings concrete information. No empty phrase like 'the project is well structured'. Use numbers, file names, symbols, code snippets. Each section must be content-rich. Action verbs, justified superlatives.\",\n dense: \"DENSE / TECHNICAL tone: maximum factual content per section. Tables, lists, code snippets, function/class names, file paths. No generalities. Every claim must be sourced by a file or a line.\",\n pedagogique: \"TEACHING tone: explain like to a junior developer. Define concepts, give analogies, concrete examples. Be clear and progressive.\",\n minimal: \"MINIMAL tone: facts, tables, lists. Minimum narrative text. Answer in bullet points.\"\n } : {\n ouf: \"Ton 'OUF' : le plus beau, dense et percutant rapport technique que l'utilisateur ait jamais vu. Bannières ASCII majestueuses, tableaux premium bordés, Mermaid, encadrés visuels, score cards, badges textuels, extraits de code avec chemins et lignes, chiffres/métriques, killer insights, citations directes du contexte, storytelling produit. AUCUNE phrase creuse. Chaque section doit être riche, stylée et actionnable. Verbes d'action, superlatifs justifiés. Fais frissonner le lecteur.\",\n punchy: \"Ton PUNCHY / DENSE : phrases courtes et percutantes, chaque ligne apporte une information concrète. Aucune phrase creuse du type 'le projet est bien structuré'. Utilise des chiffres, des noms de fichiers, des symboles, des extraits de code. Chaque section doit être riche en contenu. Verbes d'action, superlatifs justifiés.\",\n dense: \"Ton DENSE / TECHNIQUE : maximum de contenu factuel par section. Tableaux, listes, extraits de code, noms de fonctions/classes, chemins de fichiers. Aucune généralité. Chaque affirmation doit être sourcée par un fichier ou une ligne.\",\n pedagogique: \"Ton PÉDAGOGIQUE : explique comme à un développeur junior. Définis les concepts, donne des analogies, des exemples concrets. Sois clair et progressif.\",\n minimal: \"Ton MINIMAL : faits, tableaux, listes. Minimum de texte narratif. Réponds en points.\"\n };\n return `${heading}\\n${tones[style] || tones.ouf}\\n\\n`;\n}\n\nexport function buildIntelligencePrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"Intelligence Brief\" : \"Brief d'Intelligence Pro\", isEn ? \"TECHNICAL AUDIT, ARCHITECTURE & STRATEGY\" : \"AUDIT TECHNIQUE, ARCHITECTURE & STRATÉGIE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **Senior Staff Engineer / CTO en free-lance** qui réalise un **Brief d'Intelligence Pro** sur le projet \"${projectName}\". Mission : lire le code comme un pro, écouter ce qu'il dit, et produire un rapport d'audit exceptionnel, ultra-stylé et actionnable. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS == du contexte : cite les chiffres exacts et intègre des extraits de code quand c'est pertinent. Toutes les opportunités et recommandations doivent être cohérentes avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Ne pas imposer de contraintes qui ne sont pas explicitement documentées.${f}\\n\\n## Ton et style (décomplexé, pro, haut de gamme)${banner}\\n- Utilise des émojis pertinents pour chaque section\\n- Des tableaux quand c'est pertinent (stack, dette, modules, concurrents, risques)\\n- Des diagrammes Mermaid pour architecture, data flow et graphe de modules\\n- Des admonitions / citations / encadrés pour les insights clés\\n- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]\\n- Des phrases percutantes, pas de remplissage\\n\\n## Sections obligatoires (sois exhaustif mais concis — NE SAUTE AUCUNE SECTION, numérote exactement de 1 à 11)\\n1. **Executive Summary** : promesse produit + verdict technique en 4 lignes.\\n2. **Stack & Architecture** : framework, runtime, storage, state, build, tests.\\n3. **Tech Radar (Best Tech & Alternatives)** : pour chaque technologie clé, explique POURQUOI c'est le meilleur choix ici (argument massue lié au code), donne une alternative classique et un cas où elle ne serait pas aussi bonne. Sois un avocat de la stack.\\n4. **Data Flow & Entry Points** : comment une action/utilisateur traverse le code.\\n5. **Module Graph & Connexions** : qui appelle quoi, couches, hubs, feuilles.\\n6. **Security & Privacy Posture** : chiffrement, stockage, permissions, vulnérabilités potentielles.\\n7. **Errors, Debt & Smells** : TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, catch vides, etc. Cite les fichiers et lignes.\\n8. **Competitor Landscape** : 3-4 concurrents directs ou indirects de ce type d'app, points forts/différenciants de ${projectName} par rapport à eux.\\n9. **Forces & Risks** : qualité, patterns propres, dette, fragilités.\\n10. **Opportunités** : 3-5 actions concrètes priorisées (refacto, feature, test, perf, sécurité, product). Avant cette section, liste les \"Contraintes produit identifiées\" en début de contexte. Chaque action doit être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet. Si aucune contrainte, explique pourquoi elle est adaptée à la stack/architecture. Exemple : > Justification : Cette action respecte la règle \"no cloud\" en conservant toutes les données en local.\\n11. **Fait avec passion par shinzarou-eng** : une idée créative originale (feature, slogan, concept visuel ou nom de module) inspirée par le code, avec un argument marketing gagnant — dans le respect des contraintes du projet IDENTIFIEES dans le contexte. Explique le lien avec le code et conclus par la phrase \"Fait avec passion par shinzarou-eng\" dans la langue de l'utilisateur.\\n\\nReste factuel, cible les fichiers et symboles par leur chemin relatif. Ne généralise pas hors du contexte fourni. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Sections numérotées de 1 à 11.\\n- [ ] Au moins 3 métriques du contexte citées.\\n- [ ] Au moins 2 extraits de code avec chemin + ligne.\\n- [ ] Chaque opportunité a un \"> Justification :\".\\n- [ ] Aucune section vide.\\n- [ ] Pas de phrase du type \"le code est bien structuré\" sans preuve.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **Senior Staff Engineer / freelance CTO** producing a **Pro Intelligence Brief** for the project \"${projectName}\". Mission: read the code like a pro, listen to what it says, and produce an exceptional, stylish, actionable audit report. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == in the context: cite exact numbers and include code snippets when relevant. All opportunities and recommendations must be consistent with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Do not impose constraints that are not explicitly documented.${f}\\n\\n## Tone & Style (confident, pro, premium)${banner}\\n- Use relevant emojis for each section\\n- Use tables where appropriate (stack, debt, modules, competitors, risks)\\n- Mermaid diagrams for architecture, data flow and module graph\\n- Admonitions / callouts / quote boxes for key insights\\n- Text badges: [CRITICAL], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]\\n- Punchy sentences, no filler\\n\\n## Required Sections (be thorough but concise — DO NOT SKIP ANY SECTION, number them exactly 1 to 11)\\n1. **Executive Summary**: product promise + technical verdict in 4 lines.\\n2. **Stack & Architecture**: framework, runtime, storage, state, build, tests.\\n3. **Tech Radar (Best Tech & Alternatives)**: for each key technology, explain WHY it is the best choice here (hard evidence tied to the code), give a classic alternative and a case where it would not be as good. Be an advocate of the stack.\\n4. **Data Flow & Entry Points**: how an action/user traverses the code.\\n5. **Module Graph & Connections**: who calls what, layers, hubs, leaves.\\n6. **Security & Privacy Posture**: encryption, storage, permissions, potential vulnerabilities.\\n7. **Errors, Debt & Smells**: TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, empty catches, etc. Cite files and lines.\\n8. **Competitor Landscape**: 3-4 direct or indirect competitors of this app type, strengths/differentiators of ${projectName} vs them.\\n9. **Forces & Risks**: quality, unique patterns, debt, fragilities.\\n10. **Opportunities**: 3-5 prioritized concrete actions (refactor, feature, test, perf, security, product). Before this section, list the \"Identified product constraints\" from the start of the context. Each action must be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the \"no cloud\" rule by keeping all data local.\\n11. **Made with passion by shinzarou-eng**: an original creative idea (feature, slogan, visual concept or module name) inspired by the code, with a winning marketing argument — respecting the product constraints IDENTIFIED in the context. Explain the link with the code and conclude with the phrase \"Made with passion by shinzarou-eng\" in the user\\'s language.\\n\\nStay factual, target files and symbols by their relative path. Do not generalize beyond the provided context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Sections numbered 1 to 11.\\n- [ ] At least 3 metrics from the context cited.\\n- [ ] At least 2 code snippets with path + line.\\n- [ ] Each opportunity has a \"> Rationale:\".\\n- [ ] No empty section.\\n- [ ] No sentence like \"the code is well structured\" without proof.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildAuditPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Non-Compliance Audit\" : \"Audit Non-Conformités\", isEn ? \"TECHNICAL DEBT AND RISK SCAN\" : \"SCAN DE LA DETTE TECHNIQUE ET DES RISQUES\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\nTu es un **QA Lead / Staff Engineer** en charge d'un **audit de non-conformités et de dette technique** sur le projet \"${projectName}\". Mission : analyser les signaux fournis, classifier chaque problème, expliquer le risque, et proposer un correctif concret (code ou action).${f}\\n\\n## Ton et style\\n- Utilise des tableaux pour le récapitulatif\\n- Des emojis sévérité : 🔴 Critique / 🟠 Moyen / 🟡 Faible / 🔵 Info\\n- Des badges : [CRITIQUE], [DETTE], [BUG], [FIX], [RECOMMANDATION]\\n- Des blocs de code pour les correctifs\\n- Un encadré visuel de conclusion\\n\\n## Sections obligatoires (numérote exactement)\\n1. **Vue d'ensemble** : nombre total de signaux, répartition par sévérité, verdict global (code sain, dette légère, dette modérée, risque élevé).\\n2. **Tableau des non-conformités** : pour chaque signal, colonnes Fichier:Ligne, Sévérité, Type, Problème, Fix proposé (action immédiate ou code).\\n3. **Top 5 priorités** : les 5 problèmes les plus risqués ou bloquants, avec un snippet de code actuel et un snippet de code corrigé.\\n4. **Plan d'action** : 3-5 tâches concrètes pour nettoyer (par ordre de priorité).\\n5. **Conclusion** : une phrase percutante dans un encadré visuel.\\n\\nReste factuel. Ne généralise pas hors du contexte fourni. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.${banner}`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\nYou are a **QA Lead / Staff Engineer** in charge of a **non-compliance and technical debt audit** for the project \"${projectName}\". Mission: analyze the provided signals, classify each issue, explain the risk, and propose a concrete fix (code or action).${f}\\n\\n## Tone & Style\\n- Use tables for the summary\\n- Severity emojis: 🔴 Critical / 🟠 Medium / 🟡 Low / 🔵 Info\\n- Badges: [CRITICAL], [DEBT], [BUG], [FIX], [RECOMMENDATION]\\n- Code blocks for fixes\\n- A visual conclusion callout\\n\\n## Required Sections (number exactly)\\n1. **Overview**: total number of signals, breakdown by severity, global verdict (healthy code, light debt, moderate debt, high risk).\\n2. **Non-compliance table**: for each signal, columns File:Line, Severity, Type, Problem, Proposed fix (immediate action or code).\\n3. **Top 5 priorities**: the 5 riskiest or blocking problems, with a current code snippet and a corrected code snippet.\\n4. **Action plan**: 3-5 concrete cleanup tasks (in priority order).\\n5. **Conclusion**: a punchy sentence in a visual callout.\\n\\nStay factual. Do not generalize beyond the provided context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.${banner}`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function brandSignature(lang = \"fr\"): string {\n const d = new Date().toISOString().slice(0, 10);\n if (lang === \"en\") {\n return `\\n\\n---\\n\\n> ✨ *Report by **dsh-codebase-chat** v${promptVersion()} — Codebase Analysis — ${d}*\\n> 🔗 *Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.*`;\n }\n return `\\n\\n---\\n\\n> ✨ *Rapport par **dsh-codebase-chat** v${promptVersion()} — Analyse de Codebase — ${d}*\\n> 🔗 *Conçu pour DeepSeek Harness. Extensible à tout agent ou IDE Node.js.*`;\n}\n\nexport function buildAsciiBanner(projectName: string, modeLabel: string, tagline = \"\"): string {\n const raw = (projectName ?? \"\").toUpperCase().replace(/[^A-Z0-9_\\- ]/g, \"\").slice(0, 14);\n const title = raw || \"PROJECT\";\n const ascii = figlet.textSync(title, { font: \"ANSI Shadow\" });\n const lines = ascii.split(\"\\n\").filter((l) => l.trim() !== \"\");\n const subtitle1 = `${modeLabel.toUpperCase()} — ${projectName}`.slice(0, 80);\n const subtitle2 = tagline ? tagline.slice(0, 80) : \"\";\n const width = Math.max(...lines.map((l) => l.length), subtitle1.length, subtitle2.length || 0, 50);\n const pad = (s: string) => s.length < width ? s + \" \".repeat(width - s.length) : s.slice(0, width);\n const h = \"═\".repeat(width + 2);\n const center = (s: string) => {\n const s2 = s.slice(0, width);\n const spaces = Math.max(0, width - s2.length);\n const left = Math.floor(spaces / 2);\n return pad(\" \".repeat(left) + s2);\n };\n const centerArt = (s: string) => center(s);\n\n const blank = pad(\"\");\n\n const body = [\n blank,\n ...lines.map((l) => centerArt(l)),\n blank,\n center(subtitle1),\n subtitle2 ? center(subtitle2) : null,\n blank\n ]\n .filter(Boolean)\n .map((l) => `║ ${l} ║`)\n .join(\"\\n\");\n\n return `╔${h}╗\\n${body}\\n╚${h}╝`;\n}\n\nexport function bannerInstruction(projectName: string, modeLabel: string, tagline = \"\"): string {\n const banner = buildAsciiBanner(projectName, modeLabel, tagline);\n return `\\n\\n${banner}\\n\\n`;\n}\n\nexport function buildReportPrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const signature = brandSignature(lang);\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"Strategic Report\" : \"Rapport Stratégique\", isEn ? \"PROFESSIONAL BOARD-LEVEL ASSESSMENT / EXECUTIVE CTO\" : \"CONSTAT PROFESSIONNEL DE NIVEAU BOARD / EXECUTIVE CTO\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **CTO d'élite / Partner Technique** qui rédige le **Constat Professionnel ultime** sur le projet \"${projectName}\". Ce document doit être le plus beau, le plus percutant, le plus actionnable : un rapport de haut niveau prêt pour un board. Mission : fusionner architecture, dette, concurrence, résultats de tests/build, git, marketing ET respecter les contraintes produit IDENTIFIEES dans le contexte. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS == pour citer des chiffres exacts et insérer des snippets de code. Ne jamais imposer de contraintes qui ne sont pas dans le contexte.${f}\\n\\n## Identité visuelle (obligatoire)${banner}\\n- Utilise des émojis premium pour chaque section\\n- Des tableaux professionnels bordés par des lignes Markdown\\n- Des diagrammes Mermaid\\n- Des encadrés avec > pour les insights et verdicts\\n- Des \"score cards\" : Maturité, Sécurité, Maintenabilité, Performance, UX (notes sur 10 avec justification)\\n- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMANDATION].\\n- Finis par le bloc signature ci-dessous :\\n${signature}\\n\\n## Sections obligatoires (numérote exactement de 1 à 13)\\n1. **Page de Garde** : bannière, date, projet, version, auteur (DSH Codebase Analysis).\\n2. **Executive Summary** : promesse produit, verdict technique, 5 score cards sur 10, argument de pourquoi ce projet peut être le meilleur, et alignement avec les contraintes/produits IDENTIFIEES dans le contexte.\\n3. **Constat Profond** : diagnostic synthétique en 3-5 phrases fortes.\\n4. **SWOT Stratégique** : tableau 2x2 (Forces, Faiblesses, Opportunités, Menaces).\\n5. **Architecture & Tech Radar (Best-of-Breed)** : pour chaque technologie clé, explique pourquoi c'est le meilleur choix ici, donne un argument massue, un contre-argument, et une alternative classique.\\n6. **Module Graph & Connexions** : hubs, feuilles, Mermaid, points de fragilité.\\n7. **Sécurité & Confidentialité** : posture, cryptographie, vulnérabilités.\\n8. **Qualité du Code & Dette** : signaux, top risques, correctifs.\\n9. **Produit & UX** : parcours utilisateur, points de friction, idées d'amélioration.\\n10. **Paysage Concurrentiel** : positionnement vs 3-4 acteurs, avantages différenciants, règles du jeu du marché.\\n11. **Marketing & Positionnement** : persona cible, promesse unique (USP), tagline, canaux d'acquisition, argumentaire \"pourquoi on va gagner\", et **Master Move** : la feature/stratégie dominante qui fait gagner, compatible avec les contraintes du projet IDENTIFIEES dans le contexte.\\n11b. **Contraintes Produits du Projet** (avant la roadmap) : liste les contraintes explicites identifiées dans == CONTRAINTES PRODUIT IDENTIFIEES == en début de contexte. Si aucune, indique \"Aucune contrainte documentée\". Cette section sert de référence pour justifier chaque action.\\n12. **Roadmap 90 Jours & Justifications** : 4-6 actions concrètes priorisées (semaines 1-4, 5-8, 9-12) pour devenir le meilleur. Chaque action DOIT être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet. Si aucune contrainte, explique pourquoi elle est adaptée à la stack/architecture. Exemple : > Justification : Cette action respecte la règle \"100% offline\" car elle n'utilise aucun backend cloud.\\n13. **Fait avec passion par shinzarou-eng** : concept produit/visuel original, slogan percutant, et argumentaire marketing gagnant inspiré par le code — dans le respect des contraintes du projet IDENTIFIEES dans le contexte.\\n\\nReste factuel, cible les fichiers par leur chemin relatif. Ne généralise pas hors du contexte. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Sections numérotées de 1 à 13.\\n- [ ] Bannière ASCII en haut.\\n- [ ] 5 score cards avec notes /10.\\n- [ ] 1 diagramme Mermaid (architecture, data flow ou module graph).\\n- [ ] Chaque action roadmap a un \"> Justification :\".\\n- [ ] Au moins 2 citations de fichiers exactes (ligne).\\n- [ ] Conclusion \"Fait avec passion par shinzarou-eng\".`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are an **elite CTO / Technical Partner** writing the **ultimate Professional Assessment** for the project \"${projectName}\". This document must be the most beautiful, punchy and actionable: a board-ready high-level report. Mission: merge architecture, debt, competition, test/build results, git, marketing AND respect the product constraints IDENTIFIED in the context. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == to cite exact numbers and insert code snippets. Never impose constraints that are not in the context.${f}\\n\\n## Visual Identity (mandatory)${banner}\\n- Use premium emojis for each section\\n- Professional tables framed by Markdown lines\\n- Mermaid diagrams\\n- Quote boxes with > for insights and verdicts\\n- \"Score cards\": Maturity, Security, Maintainability, Performance, UX (scores out of 10 with rationale)\\n- Text badges: [CRITICAL], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMENDATION].\\n- End with the signature block below:\\n${signature}\\n\\n## Required Sections (number exactly 1 to 13)\\n1. **Cover Page**: banner, date, project, version, author (DSH Codebase Analysis).\\n2. **Executive Summary**: product promise, technical verdict, 5 score cards out of 10, argument for why this project can be the best, and alignment with the product constraints IDENTIFIED in the context.\\n3. **Deep Diagnosis**: synthetic diagnosis in 3-5 strong sentences.\\n4. **Strategic SWOT**: 2x2 table (Strengths, Weaknesses, Opportunities, Threats).\\n5. **Architecture & Tech Radar (Best-of-Breed)**: for each key technology, explain why it is the best choice here, give a hard-hitting argument, a counter-argument, and a classic alternative.\\n6. **Module Graph & Connections**: hubs, leaves, Mermaid, fragility points.\\n7. **Security & Privacy**: posture, cryptography, vulnerabilities.\\n8. **Code Quality & Debt**: signals, top risks, fixes.\\n9. **Product & UX**: user journey, friction points, improvement ideas.\\n10. **Competitive Landscape**: positioning vs 3-4 players, differentiating advantages, market rules.\\n11. **Marketing & Positioning**: target persona, unique selling proposition (USP), tagline, acquisition channels, \"why we will win\" argument, and **Master Move**: the dominant feature/strategy that makes you win, compatible with the product constraints IDENTIFIED in the context.\\n11b. **Product Constraints of the Project** (before the roadmap): list the explicit constraints identified in == IDENTIFIED PRODUCT CONSTRAINTS == at the start of the context. If none, indicate \"No documented constraints\". This section serves as a reference to justify each action.\\n12. **90-Day Roadmap & Rationale**: 4-6 prioritized concrete actions (weeks 1-4, 5-8, 9-12) to become the best. Each action MUST be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the \"100% offline\" rule by not using any cloud backend.\\n13. **Made with passion by shinzarou-eng**: an original product/visual concept, a punchy slogan, and a winning marketing argument inspired by the code — respecting the product constraints IDENTIFIED in the context.\\n\\nStay factual, target files by their relative path. Do not generalize beyond the context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Sections numbered 1 to 13.\\n- [ ] ASCII banner at the top.\\n- [ ] 5 score cards with scores out of 10.\\n- [ ] 1 Mermaid diagram (architecture, data flow or module graph).\\n- [ ] Each roadmap action has a \"> Rationale:\".\\n- [ ] At least 2 exact file citations (line).\\n- [ ] Conclusion \"Made with passion by shinzarou-eng\".`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildTasksPrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"TASKS Action Plan\" : \"Plan d'Action TASKS\", isEn ? \"EXECUTABLE ROADMAP AND PRIORITIZED SPRINTS\" : \"ROADMAP EXÉCUTABLE ET SPRINTS PRIORISÉS\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **Delivery Lead / CTO** qui transforme un rapport de codebase en **plan d'action exécutable** pour le projet \"${projectName}\". RÈGLE D'OR : la section == TÂCHES GÉNÉRÉES DEPUIS LES SIGNAUX == contient déjà les tâches avec leurs blocs Avant/Après. Tu DOIS les recopier TELLES QUELLES dans le TASKS.md final, les organiser en sprints (P0, P1, P2, P3), et conserver OBLIGATOIREMENT les blocs Avant et Après FOURNIS. Tu as le droit d'ajouter 2-3 tâches maximum si tu identifies un risque majeur absent, mais la majorité du plan doit venir des tâches pré-générées. Chaque tâche doit être compatible avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Avant la liste des tâches, ajoute une section \"Contraintes produit identifiées\" pour servir de référence.${f}\\n\\n## Ton et style${banner}\\n- Un titre clair :\\n~~~markdown\\n# TASKS.md — Plan d'action ${projectName}\\n~~~\\n- Des tableaux avec colonnes : Priorité, Tâche, Fichier(s) concerné(s), Difficulté (1-5), Impact, Livrable\\n- Des checklists Markdown : '[ ]' / '[x]'\\n- Des sprints : Sprint 1 (semaines 1-2), Sprint 2, Sprint 3\\n- Des badges : [CRITIQUE], [RAPIDE], [STRATEGIQUE], [TECH-DEBT].\\n- Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\\n\\n## Sections obligatoires\\n1. **Vue d'ensemble** : 3-5 tâches prioritaires dans un tableau.\\n2. **Sprint 1 — Fondations** : sécurité, stabilité, tests.\\n3. **Sprint 2 — Amélioration** : refacto, UX, performance.\\n4. **Sprint 3 — Différenciation** : features gagnantes, marketing.\\n5. **Checklist globale** : toutes les tâches avec '[ ]'.\\n\\nChaque tâche doit être actionnable, citer un chemin de fichier relatif quand c'est possible, et être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet.\\n\\n## Exigence AVANT / APRÈS\\nPour CHAQUE tâche, ajoute obligatoirement deux blocs de code :\\n- **Avant** : extrait du code actuel (max 10 lignes) depuis le contexte == TECH DEBT & SIGNALS == ou == EXTRAITS DE CODE CLÉS ==.\\n- **Après** : extrait du code corrigé proposé (max 10 lignes).\\n\\nExemple de format :\\n- [ ] **[TASK-01] Typer l'événement SpeechRecognition**\\n - Fichier : src/components/KodaAssistantModal.tsx:651\\n - Avant :\\n --- code ts ---\\n recognition.onresult = (event: any) => { ... };\\n ---\\n - Après :\\n --- code ts ---\\n recognition.onresult = (event: SpeechRecognitionEvent) => { ... };\\n ---\\n > Justification : ...\\n\\nSi tu ne peux pas extraire l'extrait, cite au minimum le fichier et la ligne.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] 5 sections présentes (Vue d'ensemble, Sprint 1, Sprint 2, Sprint 3, Checklist globale).\\n- [ ] Toutes les tâches ont un statut '[ ]'.\\n- [ ] Chaque tâche a un bloc **Avant** (code actuel) et un bloc **Après** (code proposé), ou 'N/A' avec explication.\\n- [ ] Chaque tâche a un Fichier:Ligne.\\n- [ ] Chaque tâche a un \"> Justification :\".\\n- [ ] Conclusion \"Fait avec passion par shinzarou-eng\".\\n\\nSi aucune contrainte n'est trouvée, écris \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **Delivery Lead / CTO** turning a codebase report into an **executable action plan** for the project \"${projectName}\". GOLDEN RULE: the section == TASKS GENERATED FROM SIGNALS == already contains the tasks with their Before/After blocks. You MUST copy them AS-IS into the final TASKS.md, organize them into sprints (P0, P1, P2, P3), and OBLIGATORILY keep the provided Before and After blocks. You may add 2-3 extra tasks at most if you identify a major missing risk, but the majority of the plan must come from the pre-generated tasks. Each task must be compatible with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Before the task list, add an \"Identified product constraints\" section as a reference.${f}\\n\\n## Tone & Style${banner}\\n- A clear title:\\n~~~markdown\\n# TASKS.md — Action Plan ${projectName}\\n~~~\\n- Tables with columns: Priority, Task, Concerned file(s), Difficulty (1-5), Impact, Deliverable\\n- Markdown checklists: '[ ]' / '[x]'\\n- Sprints: Sprint 1 (weeks 1-2), Sprint 2, Sprint 3\\n- Badges: [CRITICAL], [QUICK], [STRATEGIC], [TECH-DEBT].\\n- Conclude with: Made with passion by shinzarou-eng (in the user\\'s language)\\n\\n## Required Sections\\n1. **Overview**: 3-5 prioritized tasks in a table.\\n2. **Sprint 1 — Foundations**: security, stability, tests.\\n3. **Sprint 2 — Improvement**: refactor, UX, performance.\\n4. **Sprint 3 — Differentiation**: winning features, marketing.\\n5. **Global Checklist**: all tasks with '[ ]'.\\n\\nEach task must be actionable, cite a relative file path when possible, and be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules.\\n\\n## BEFORE / AFTER Requirement\\nFor EACH task, you MUST add two code blocks:\\n- **Before**: current code snippet (max 10 lines) from == TECH DEBT & SIGNALS == or == KEY CODE SNIPPETS == in the context.\\n- **After**: proposed fixed code snippet (max 10 lines).\\n\\nExample format:\\n- [ ] **[TASK-01] Type the SpeechRecognition event**\\n - File: src/components/KodaAssistantModal.tsx:651\\n - Before:\\n --- code ts ---\\n recognition.onresult = (event: any) => { ... };\\n ---\\n - After:\\n --- code ts ---\\n recognition.onresult = (event: SpeechRecognitionEvent) => { ... };\\n ---\\n > Rationale : ...\\n\\nIf you cannot extract the snippet, at least cite the file and line.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] 5 sections present (Overview, Sprint 1, Sprint 2, Sprint 3, Global Checklist).\\n- [ ] All tasks have status '[ ]'.\\n- [ ] Each task has a **Before** (current code) and an **After** (proposed code) block, or 'N/A' with explanation.\\n- [ ] Each task has a File:Line.\\n- [ ] Each task has a \"> Rationale:\".\\n- [ ] Conclusion \"Made with passion by shinzarou-eng\".\\n\\nIf no constraints are found, write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildCeoPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(\"ouf\", lang);\n const signature = brandSignature(lang);\n const banner = bannerInstruction(projectName, isEn ? \"One-Page CEO Brief\" : \"One-Page CEO Brief\", isEn ? \"EXECUTIVE SUMMARY FOR DECISION MAKERS\" : \"EXECUTIVE SUMMARY POUR DÉCIDEUR\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **CTO / CEO / Partner** qui rédige le **One-Page Executive Brief** ultime sur le projet \"${projectName}\". RÈGLE D'OR : ce document tient sur UNE SEULE PAGE A4. MAXIMUM 7 sections courtes. Pas de blabla, que des insights à fort impact, des chiffres, des verdicts, des actions. Chaque section max 5-8 lignes. Utilise tableaux et listes. Si tu dépasses une page, tu as échoué.${f}\\n\\n## Identité visuelle (obligatoire)${banner}\\n- Tableau exécutif unique avec les metrics clés.\\n- 5 score cards (sur 10) avec justification en UNE phrase.\\n- Encadrés visuels pour les insights.\\n- Badges : [CRITIQUE], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].\\n- Conclus par le bloc signature ci-dessous :\\n${signature}\\n\\n## Sections obligatoires (numérote de 1 à 7, STRICTEMENT 1 PAGE)\\n1. **Bannière & Titre** : 1 ligne.\\n2. **Executive Summary** : 3 phrases + 1 tableau 4 métriques.\\n3. **Verdict du board** : 5 score cards, 1 ligne chacune (Domaine | Note | 5 mots de justification).\\n4. **Top 3 risques / dette** : 1 ligne par risque (Fichier:Ligne - Problème - Impact).\\n5. **Top 3 opportunités / Killer Moves** : 1 phrase par action + Justification en 1 phrase.\\n6. **SWOT ultra-concis** : 4 cases, max 4 points de 3-5 mots chacun.\\n7. **Fait avec passion par shinzarou-eng** : 1 concept + 1 slogan + 1 phrase marketing.\\n\\nReste factuel, cible les fichiers par leur chemin relatif. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS ==. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Exactement 7 sections numérotées.\\n- [ ] Le document tient sur une page (max 60-80 lignes au total).\\n- [ ] 5 score cards, 1 ligne chacune.\\n- [ ] Top 3 risques avec Fichier:Ligne.\\n- [ ] Top 3 opportunités avec \"> Justification :\".\\n- [ ] SWOT : 4 points de 3-5 mots par case.\\n- [ ] Aucun Mermaid, aucun tableau géant, aucune explication longue.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **CTO / CEO / Partner** writing the ultimate **One-Page Executive Brief** for the project \"${projectName}\". GOLDEN RULE: this document fits on a SINGLE A4 page. MAXIMUM 7 short sections. No filler, only high-impact insights, numbers, verdicts, actions. Each section max 5-8 lines. Use tables and lists. If you exceed one page, you failed.${f}\\n\\n## Visual Identity (mandatory)${banner}\\n- Single executive table with key metrics.\\n- 5 score cards (out of 10) with rationale in ONE sentence.\\n- Visual callouts for insights.\\n- Badges: [CRITICAL], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].\\n- Conclude with the signature block below:\\n${signature}\\n\\n## Required Sections (number 1 to 7, STRICTLY 1 PAGE)\\n1. **Banner & Title**: 1 line.\\n2. **Executive Summary**: 3 sentences + 1 table with 4 metrics.\\n3. **Board verdict**: 5 score cards, 1 line each (Area | Score | 5-word rationale).\\n4. **Top 3 risks / debt**: 1 line per risk (File:Line - Problem - Impact).\\n5. **Top 3 opportunities / Killer Moves**: 1 sentence per action + Rationale in 1 sentence.\\n6. **Ultra-concise SWOT**: 4 boxes, max 4 points of 3-5 words each.\\n7. **Made with passion by shinzarou-eng**: 1 concept + 1 slogan + 1 marketing sentence.\\n\\nStay factual, target files by their relative path. Leverage == PROJECT METRICS == and == KEY CODE SNIPPETS ==. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Exactly 7 numbered sections.\\n- [ ] Document fits on one page (max 60-80 lines total).\\n- [ ] 5 score cards, 1 line each.\\n- [ ] Top 3 risks with File:Line.\\n- [ ] Top 3 opportunities with \"> Rationale:\".\\n- [ ] SWOT: 4 points of 3-5 words per box.\\n- [ ] No Mermaid, no giant table, no long explanation.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildBuildPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Build Benchmark\" : \"Build Benchmark\", isEn ? \"BUILD PERFORMANCE & BUNDLE\" : \"PERFORMANCE DE BUILD & BUNDLE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **Staff Engineer / Build Performance Expert**. Analyse le résultat du build du projet \"${projectName}\". Produis un rapport ultra-concis et percutant.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"BUILD BENCHMARK — ${(projectName ?? \"\").toUpperCase()}\"\\n- 3 score cards : Vitesse, Taille du bundle, Stabilité (notes /10)\\n- Tableau des fichiers de sortie (nom, taille)\\n- Top 3 leviers d'optimisation\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **Staff Engineer / Build Performance Expert**. Analyze the build result of the project \"${projectName}\". Produce an ultra-concise, punchy report.${f}\\n\\n## Expected format\\n- ASCII banner: \"BUILD BENCHMARK — ${(projectName ?? \"\").toUpperCase()}\"\\n- 3 score cards: Speed, Bundle size, Stability (scores out of 10)\\n- Output files table (name, size)\\n- Top 3 optimization levers\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildPlayerPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Player Brief\" : \"Player Brief\", isEn ? \"USER JOURNEY & EXPERIENCE\" : \"PARCOURS UTILISATEUR & EXPÉRIENCE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **UX Researcher / Playtester / Product Hunter** qui réalise un **Player Brief** sur le projet \"${projectName}\". Tu ne regardes pas le code comme un dev, mais comme un vrai utilisateur final qui découvre l'app, clique, se frustre, se réjouit. Mission : décrire l'expérience vécue, identifier les moments clés, les frictions et les opportunités de 'wow'.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"PLAYER BRIEF — ${(projectName ?? \"\").toUpperCase()}\"\\n- Score cards : Onboarding, Clarté, Réactivité, Confiance, Plaisir (sur 10)\\n- Tableau du parcours utilisateur : Étape, Action, Sentiment, Friction, Fix\\n- Top 5 moments 'Wow' (ce qui impressionne)\\n- Top 5 frictions bloquantes ou irritantes\\n- Idées de gamification / engagement (si pertinent)\\n- Roadmap UX 30 jours : 3 actions rapides d'impact utilisateur\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **UX Researcher / Playtester / Product Hunter** producing a **Player Brief** for the project \"${projectName}\". You do not look at the code like a dev, but like a real end user discovering the app, clicking, getting frustrated, getting delighted. Mission: describe the lived experience, identify key moments, frictions and 'wow' opportunities.${f}\\n\\n## Expected format\\n- ASCII banner: \"PLAYER BRIEF — ${(projectName ?? \"\").toUpperCase()}\"\\n- Score cards: Onboarding, Clarity, Responsiveness, Trust, Delight (out of 10)\\n- User journey table: Step, Action, Sentiment, Friction, Fix\\n- Top 5 'Wow' moments (what impresses)\\n- Top 5 blocking or annoying frictions\\n- Gamification / engagement ideas (if relevant)\\n- 30-day UX roadmap: 3 quick high-impact actions\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildGitPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Git Intelligence\" : \"Git Intelligence\", isEn ? \"HISTORY, HOTSPOTS & RISKS\" : \"HISTORIQUE, HOTSPOTS & RISQUES\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **Tech Lead** qui analyse l'historique git du projet \"${projectName}\". Résume l'activité, identifie les tendances, les hotspots de modification et les risques récents.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"GIT INTELLIGENCE — ${(projectName ?? \"\").toUpperCase()}\"\\n- Derniers commits synthétisés\\n- Hotspots (fichiers qui bougent le plus)\\n- Risques récents\\n- Suggestions de prochaines actions\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **Tech Lead** analyzing the git history of the project \"${projectName}\". Summarize activity, identify trends, modification hotspots and recent risks.${f}\\n\\n## Expected format\\n- ASCII banner: \"GIT INTELLIGENCE — ${(projectName ?? \"\").toUpperCase()}\"\\n- Synthesized recent commits\\n- Hotspots (files that change the most)\\n- Recent risks\\n- Suggested next actions\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildApplyPrompt(filePath: string, newContent: string, projectName: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const fr = `Applique la mise à jour suivante au fichier \"${filePath}\" du projet \"${projectName}\".\\n\\n${langInstruction(lang)}\\n\\nTu es un **Staff Engineer**. Le contenu fourni est la nouvelle version complète du fichier. Réponds UNIQUEMENT par :\\n\\n- Si le patch semble correct : \"Fichier ${filePath} mis à jour avec succès.\"\\n- Si tu refuses : dis pourquoi en une phrase.\\n\\nFait avec passion par shinzarou-eng.\\n\\n---\\n\\nNouveau contenu :\\n~~~\\n${newContent.slice(0, 8000)}\\n~~~`;\n const en = `Apply the following update to file \"${filePath}\" in project \"${projectName}\".\\n\\n${langInstruction(lang)}\\n\\nYou are a **Staff Engineer**. The provided content is the complete new version of the file. Respond ONLY with:\\n\\n- If the patch looks correct: \"File ${filePath} updated successfully.\"\\n- If you refuse: say why in one sentence.\\n\\nMade with passion by shinzarou-eng.\\n\\n---\\n\\nNew content:\\n~~~\\n${newContent.slice(0, 8000)}\\n~~~`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nconst TOOL_BUILDERS: Record<string, (o: Required<Pick<ToolPromptOptions, 'context' | 'projectName'>> & ToolPromptOptions) => string> = {\n codebase_intelligence: (o) => buildIntelligencePrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_report: (o) => buildReportPrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_audit: (o) => buildAuditPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_tasks: (o) => buildTasksPrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_ceo: (o) => buildCeoPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_player: (o) => buildPlayerPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_search: (o) => buildSearchPrompt(o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_explain: (o) => buildExplainPrompt(o.filePath || o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_refactor: (o) => buildRefactorPrompt(o.filePath || o.focus || '', o.description || o.query || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_chat: (o) => buildChatPrompt(o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_crea: (o) => buildCreaPrompt(o.focus || o.query || 'creative idea', o.context, o.projectName, o.lang || 'fr'),\n};\n\n/**\n * Assemble the full LLM prompt (context + persona + mandatory sections +\n * ASCII banner + citation rules) for a codebase_* tool — the same text the\n * DeepSeek Harness plugin sends, so MCP clients and the CLI get identical\n * reports. Unknown tool names throw.\n */\nexport function buildToolPrompt(tool: string, opts: ToolPromptOptions): string {\n const builder = TOOL_BUILDERS[tool];\n if (!builder) throw new Error(`unknown prompt tool: ${tool}`);\n return normalizeLabels(builder(opts), opts.lang || 'fr');\n}\n","// Embedded local LLM — a small GGUF model served by node-llama-cpp, downloaded\n// into the shared cache dir on first use. Enables fully-offline answers with\n// no API key and no host model. Quality is limited vs hosted models, so it is\n// opt-in via CODEBASE_LOCAL_LLM, the `localLlm` tool argument or `--local`.\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getCacheDir } from './project.js';\n\n// Small instruct model (~1 GB, CPU-friendly). Override with CODEBASE_LOCAL_LLM\n// set to an `hf:owner/repo:QUANT` URI or an absolute path to a .gguf file.\nconst DEFAULT_MODEL_URI = 'hf:Qwen/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M';\nconst LOCAL_CONTEXT_SIZE = 8192;\nconst LOCAL_MAX_TOKENS = 1536;\n\nexport function isLocalLlmEnabled(): boolean {\n return !!(process.env.CODEBASE_LOCAL_LLM || '').trim();\n}\n\nfunction configuredModel(): string {\n const v = (process.env.CODEBASE_LOCAL_LLM || '').trim();\n if (!v || v === '1' || v.toLowerCase() === 'true') return DEFAULT_MODEL_URI;\n return v;\n}\n\nasync function importLlama(): Promise<any> {\n try {\n return await import('node-llama-cpp');\n } catch {\n throw new Error('Local LLM needs the optional dependency: npm i node-llama-cpp');\n }\n}\n\nlet modelPromise: Promise<any> | null = null;\n\nfunction loadLocalModel(): Promise<any> {\n if (!modelPromise) {\n modelPromise = (async () => {\n const spec = configuredModel();\n let modelPath = spec;\n if (spec.startsWith('hf:')) {\n const { createModelDownloader } = await importLlama();\n const downloader = await createModelDownloader({\n modelUri: spec,\n dirPath: join(getCacheDir(), 'models'),\n });\n modelPath = await downloader.download();\n } else if (!existsSync(spec)) {\n throw new Error(`Local model not found: ${spec}`);\n }\n const { getLlama } = await importLlama();\n const llama = await getLlama();\n return llama.loadModel({ modelPath });\n })();\n modelPromise.catch(() => { modelPromise = null; });\n }\n return modelPromise;\n}\n\nexport async function callLocalLlm(prompt: string, lang = 'fr'): Promise<string> {\n const model = await loadLocalModel();\n const { LlamaChatSession } = await importLlama();\n const context = await model.createContext({ contextSize: LOCAL_CONTEXT_SIZE });\n try {\n const session = new LlamaChatSession({\n contextSequence: context.getSequence(),\n systemPrompt: lang === 'en'\n ? 'You are a senior codebase analyst. Be precise and cite files with [source: path:line].'\n : 'Tu es un analyste codebase senior. Sois precis et cite les fichiers avec [source: chemin:ligne].',\n });\n return await session.prompt(prompt, {\n temperature: 0.2,\n maxTokens: LOCAL_MAX_TOKENS,\n // Small models degenerate into loops at low temperature — penalize\n // repeated tokens so the answer moves forward instead of echoing.\n repeatPenalty: { lastTokens: 128, penalty: 1.2, penalizeNewLine: false },\n });\n } finally {\n await context.dispose();\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","sep","join","extname","join","relative","sep","readFile","extname","relative","sep","readFile","join","score","t","basename","readFile","join","basename","readFile","join","t","t","existsSync","join","join","existsSync"]}
1
+ {"version":3,"sources":["../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","../src/prompts.ts","../src/local-llm.ts"],"sourcesContent":["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, walk.skipFiles, walk.ignoreGlobs);\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 'target', 'bin', 'obj', 'vendor', '.venv', 'venv', '__pycache__',\r\n '.npm-cache', '.parcel-cache', '.gradle', '.mypy_cache', '.pytest_cache',\r\n 'android', 'ios', 'e2e-shots', 'playstore_screenshots',\r\n '.cursor', '.idea', '.memsearch', '.vscode',\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) && !skipDirs.has(rel) && !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, skipFiles = DEFAULT_SKIP_FILES, ignoreGlobs: string[] = []): 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 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) || skipDirs.has(rel) || matchesAnyGlob(rel, ignoreGlobs)) continue;\r\n lines.push(`${prefix}${entry.name}/`);\r\n await walk(fullPath, `${prefix} `);\r\n } else {\r\n if (skipFiles.has(entry.name) || matchesAnyGlob(rel, ignoreGlobs)) continue;\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. Globs without `/` match the basename at any depth (gitignore-style). */\nexport function matchesAnyGlob(relPath: string, globs: string[] | undefined): boolean {\n if (!globs || globs.length === 0) return false;\n const rel = relPath.replace(/\\\\/g, '/');\n const base = rel.split('/').pop() ?? rel;\n return globs.some(g => {\n const re = globToRegExp(g);\n return re.test(rel) || (!g.includes('/') && re.test(base));\n });\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 if (r.analyzedFiles === 0) {\r\n out.push(lang === 'en'\r\n ? 'No code files detected in this project — check the path or your .codebase-chat.json ignore rules.'\r\n : 'Aucun fichier de code détecté dans ce projet — vérifie le chemin ou les règles ignore de .codebase-chat.json.');\r\n return out.join('\\n');\r\n }\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 if (r.analyzedFiles === 0) {\r\n out.push(lang === 'en'\r\n ? '_No code files detected in this project — check the path or your `.codebase-chat.json` ignore rules._'\r\n : '_Aucun fichier de code détecté dans ce projet — vérifie le chemin ou les règles ignore de `.codebase-chat.json`._');\r\n return out.join('\\n');\r\n }\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","import { readFileSync } from 'node:fs';\nimport figlet from 'figlet';\n\nlet cachedVersion: string | undefined;\nfunction promptVersion(): string {\n if (!cachedVersion) {\n try {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { version?: string };\n cachedVersion = pkg.version ?? '0.0.0';\n } catch {\n cachedVersion = '0.0.0';\n }\n }\n return cachedVersion;\n}\n\nexport interface ToolPromptOptions {\n context: string;\n projectName: string;\n lang?: string;\n style?: string;\n query?: string;\n focus?: string;\n filePath?: string;\n description?: string;\n crea?: boolean;\n creaTheme?: string;\n}\n\nexport function citationInstruction(lang = \"fr\"): string {\n const isEn = lang === \"en\";\n return `${isEn ? \"## Evidence & Scoring (mandatory)\" : \"## Sources & Scoring (obligatoire)\"}\\n- ${isEn ? \"Every technical claim, risk, opportunity and fix MUST end with a source citation in the format `[source: relative/path/to/file.ts:line]` (e.g. `[source: src/App.tsx:42]`).\" : \"Chaque affirmation technique, risque, opportunité et correctif DOIT se terminer par une citation source au format `[source: chemin/relatif/vers/fichier.ts:ligne]` (ex. `[source: src/App.tsx:42]`).\"}\\n- ${isEn ? \"Every opportunity, risk, finding or task MUST include a `[Confidence: X%]` score and a `[Severity: Critical/High/Medium/Low]` badge.\" : \"Chaque opportunité, risque, constat ou tâche DOIT inclure un score `[Confiance : X%]` et un badge `[Sévérité : Critique/Élevée/Moyenne/Faible]`.\"}\\n- ${isEn ? \"Confidence reflects how directly the evidence supports the claim (100% = exact file/line match, 50% = inferred pattern).\" : \"La confiance reflète à quel point l'evidence supporte directement l'affirmation (100% = correspondance exacte fichier/ligne, 50% = pattern inféré).\"}\\n- ${isEn ? \"Do not invent citations. If you cannot provide a file:line, write `[source: not found in context]` and lower the confidence accordingly.\" : \"Ne pas inventer de citations. Si vous ne pouvez pas donner fichier:ligne, écrivez `[source: non trouvé dans le contexte]` et baissez la confiance en conséquence.\"}\\n`;\n}\n\nexport function withCitations(prompt: string, lang = \"fr\"): string {\n return `${prompt}\\n\\n${citationInstruction(lang)}`;\n}\n\nexport function langInstruction(lang = \"fr\"): string {\n if (lang === \"en\") {\n return \"IMPORTANT: This whole prompt is in French for context, but the user requested English. Your ENTIRE response MUST be written in English. Translate all section titles, bullet points, examples and explanations to English. Do not output any French words except quoted code or file paths.\";\n }\n return \"IMPORTANT: Reponds obligatoirement en francais. Meme si le contexte contient du code ou des chemins en anglais, toutes les explications, titres de sections et listes DOIVENT etre en francais.\";\n}\n\nexport function normalizeLabels(prompt: string, lang: string): string {\n if (lang !== \"en\") return prompt;\n const map = {\n \"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language).\",\n \"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language)\",\n \"Conclus par la phrase-clé \\\"Fait avec passion par shinzarou-eng\\\" dans la langue de l'utilisateur.\": \"Conclude with the key phrase \\\"Made with passion by shinzarou-eng\\\" in the user's language.\",\n \"Conclus par la phrase-clé \\\"Fait avec passion par shinzarou-eng\\\" dans la langue de l'utilisateur\": \"Conclude with the key phrase \\\"Made with passion by shinzarou-eng\\\" in the user's language\",\n \"Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\": \"Conclude with: Made with passion by shinzarou-eng (in the user's language)\",\n \"Fait avec passion par shinzarou-eng\": \"Made with passion by shinzarou-eng\",\n \"Justification\": \"Rationale\",\n \"Avant :\": \"Before:\",\n \"Avant:\": \"Before:\",\n \"Après :\": \"After:\",\n \"Après:\": \"After:\",\n \"Contraintes produit IDENTIFIEES\": \"IDENTIFIED PRODUCT CONSTRAINTS\",\n \"Contraintes produit identifiees\": \"Identified product constraints\",\n \"CONTRAINTES PRODUIT IDENTIFIEES\": \"IDENTIFIED PRODUCT CONSTRAINTS\",\n \"Ton et style\": \"Tone and style\",\n \"Sections obligatoires\": \"Required sections\",\n \"CHECKLIST FINALE\": \"FINAL CHECKLIST\",\n \"Vue d'ensemble\": \"Overview\",\n \"Fondations (Sécurité / Stabilité)\": \"Foundations (Security / Stability)\",\n \"Amélioration (Refacto / Qualité)\": \"Improvement (Refactor / Quality)\",\n \"Optimisation (Perf / Tests)\": \"Optimization (Performance / Tests)\",\n \"Différenciation (UX / Produit)\": \"Differentiation (UX / Product)\",\n \"Fichier(s) concerné(s)\": \"Concerned file(s)\",\n \"Difficulté\": \"Difficulty\",\n \"Livrable\": \"Deliverable\",\n \"Priorité\": \"Priority\",\n \"Tâche\": \"Task\",\n \"Fichier non trouve\": \"File not found\",\n \"Rapport généré par\": \"Report by\",\n \"Conçu pour DeepSeek Harness. Extensible à tout agent ou IDE Node.js.\": \"Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.\",\n \"Analyse de Codebase\": \"Codebase Analysis\",\n \"Projet\": \"Project\",\n \"Arborescence\": \"File tree\",\n \"Aucune contrainte explicite documentee.\": \"No explicit constraints documented.\"\n };\n let out = prompt;\n for (const [fr, en] of Object.entries(map)) {\n out = out.replaceAll(fr, en);\n }\n return out;\n}\n\nexport function creaFooter(_projectName: string, theme: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const t = theme || (isEn ? \"a creative proposal adapted\" : \"une proposition creative adaptee\");\n if (isEn) {\n return `\\n\\n---\\n\\nMade with passion by shinzarou-eng: from this analysis, generate a creative thing on the theme \"${t}\" (slogan, feature name, tagline, visual concept, marketing one-liner, or feature idea). Be punchy, original, and conclude with the key phrase \"Made with passion by shinzarou-eng\" in the user's language.`;\n }\n return `\\n\\n---\\n\\nFait avec passion par shinzarou-eng : à partir de cette analyse, génère un truc créatif sur le thème \"${t}\" (slogan, nom de feature, tagline, concept visuel, one-liner marketing, ou idée de fonctionnalité). Sois percutant, original, et conclus par la phrase-clé \"Fait avec passion par shinzarou-eng\" dans la langue de l'utilisateur.`;\n}\n\nexport function buildChatPrompt(question: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Codebase Chat\" : \"Codebase Chat\", isEn ? \"QUESTION / ANSWER\" : \"QUESTION / RÉPONSE\");\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a codebase expert assistant. Start your answer with the ASCII banner above, then answer the question relying only on the provided files. Cite relevant files and lines.` : `Tu es un assistant expert en codebase. Commence ta réponse par la bannière ASCII ci-dessus, puis réponds à la question en t'appuyant uniquement sur les fichiers fournis. Cite les fichiers et lignes pertinents.`}\\n\\n${isEn ? \"Question\" : \"Question\"} : ${question}\\n\\n${isEn ? \"Answer\" : \"Réponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildSearchPrompt(query: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Codebase Search\" : \"Codebase Search\", `${isEn ? \"SEARCH\" : \"RECHERCHE\"} : ${query}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a codebase search engine. Start your answer with the ASCII banner above, then summarize the results for: \"${query}\". Cite relevant paths and snippets as a prioritized list.` : `Tu es un moteur de recherche codebase. Commence ta réponse par la bannière ASCII ci-dessus, puis résume les résultats pour : \"${query}\". Cite les chemins et extraits pertinents sous forme de liste priorisée.`}\\n\\n${isEn ? \"Answer\" : \"Réponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildExplainPrompt(target: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const banner = bannerInstruction(projectName, isEn ? \"Explanation\" : \"Explication\", `${isEn ? \"FILE OR SYMBOL\" : \"FICHIER OU SYMBOLE\"} : ${target}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `Explain how \"${target}\" works in this project. Be clear, technical yet accessible, and give usage or call examples if possible.` : `Explique le fonctionnement de \"${target}\" dans ce projet. Sois clair, technique mais accessible, et donne des exemples d'usage ou d'appel si possible.`}\\n\\n${isEn ? \"Answer\" : \"Reponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildRefactorPrompt(filePath: string, description: string, context: string, projectName: string, crea = false, creaTheme = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const desc = description || (isEn ? \"improve the file\" : \"ameliorer le fichier\");\n const banner = bannerInstruction(projectName, isEn ? \"Refactor\" : \"Refactor\", `${isEn ? \"FILE\" : \"FICHIER\"} : ${filePath}`);\n let prompt = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\n${isEn ? `You are a senior architect. Refactor the file \"${filePath}\" according to the following request: ${desc}\\n\\nProvide production-ready code, explain the changes, and indicate any regressions to check.` : `Tu es un architecte senior. Refactorise le fichier \"${filePath}\" selon la demande suivante : ${desc}\\n\\nPropose du code pret a l'emploi, explique les changements, et indique les eventuelles regressions a verifier.`}\\n\\n${isEn ? \"Answer\" : \"Reponse\"} :`;\n if (crea) prompt += creaFooter(projectName, creaTheme, lang);\n return withCitations(prompt, lang);\n}\n\nexport function buildCreaPrompt(theme: string, context: string, projectName: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const t = theme || (isEn ? \"a creative proposal inspired by this project\" : \"une proposition creative inspiree par ce projet\");\n const banner = bannerInstruction(projectName, isEn ? \"Crea / Ideation\" : \"Créa / Ideation\", `${isEn ? \"THEME\" : \"THÈME\"} : ${t}`);\n const base = isEn\n ? `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a creative director / growth hacker. Analyze this codebase and generate a creative and marketing proposal for the project \"${projectName}\" on the theme \"${t}\". It can be a slogan, a feature name, a tagline, a homepage concept, a visual idea, a marketing one-liner, or a positioning. Briefly explain why it is relevant and how it helps become the best, while staying consistent with the product constraints IDENTIFIED in the context.\\n\\nConclude with: Made with passion by shinzarou-eng (in the user's language).`\n : `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un directeur creatif / growth hacker. Analyse ce codebase et génère une proposition créative et marketing pour le projet \"${projectName}\" sur le thème \"${t}\". Peut être un slogan, un nom de feature, une tagline, un concept de page d'accueil, une idée visuelle, un one-liner marketing, ou un positionnement. Explique brièvement pourquoi c'est pertinent et comment ça aide à devenir le meilleur, en restant cohérent avec les contraintes du projet IDENTIFIEES dans le contexte.\\n\\nConclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).`;\n return withCitations(base, lang);\n}\n\nexport function styleInstruction(style = \"ouf\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const heading = isEn ? \"## Writing Style (mandatory)\" : \"## Style de rédaction (obligatoire)\";\n const tones: Record<string, string> = isEn ? {\n ouf: \"'WOW' tone: the most beautiful, dense and punchy technical report the user has ever seen. Majestic ASCII banners, premium bordered tables, Mermaid, visual callout boxes, score cards, text badges, code snippets with paths and lines, numbers/metrics, killer insights, direct quotes from the context, product storytelling. ZERO empty phrases. Each section must be rich, stylish and actionable. Action verbs, justified superlatives. Give the reader chills.\",\n punchy: \"PUNCHY / DENSE tone: short and punchy sentences, every line brings concrete information. No empty phrase like 'the project is well structured'. Use numbers, file names, symbols, code snippets. Each section must be content-rich. Action verbs, justified superlatives.\",\n dense: \"DENSE / TECHNICAL tone: maximum factual content per section. Tables, lists, code snippets, function/class names, file paths. No generalities. Every claim must be sourced by a file or a line.\",\n pedagogique: \"TEACHING tone: explain like to a junior developer. Define concepts, give analogies, concrete examples. Be clear and progressive.\",\n minimal: \"MINIMAL tone: facts, tables, lists. Minimum narrative text. Answer in bullet points.\"\n } : {\n ouf: \"Ton 'OUF' : le plus beau, dense et percutant rapport technique que l'utilisateur ait jamais vu. Bannières ASCII majestueuses, tableaux premium bordés, Mermaid, encadrés visuels, score cards, badges textuels, extraits de code avec chemins et lignes, chiffres/métriques, killer insights, citations directes du contexte, storytelling produit. AUCUNE phrase creuse. Chaque section doit être riche, stylée et actionnable. Verbes d'action, superlatifs justifiés. Fais frissonner le lecteur.\",\n punchy: \"Ton PUNCHY / DENSE : phrases courtes et percutantes, chaque ligne apporte une information concrète. Aucune phrase creuse du type 'le projet est bien structuré'. Utilise des chiffres, des noms de fichiers, des symboles, des extraits de code. Chaque section doit être riche en contenu. Verbes d'action, superlatifs justifiés.\",\n dense: \"Ton DENSE / TECHNIQUE : maximum de contenu factuel par section. Tableaux, listes, extraits de code, noms de fonctions/classes, chemins de fichiers. Aucune généralité. Chaque affirmation doit être sourcée par un fichier ou une ligne.\",\n pedagogique: \"Ton PÉDAGOGIQUE : explique comme à un développeur junior. Définis les concepts, donne des analogies, des exemples concrets. Sois clair et progressif.\",\n minimal: \"Ton MINIMAL : faits, tableaux, listes. Minimum de texte narratif. Réponds en points.\"\n };\n return `${heading}\\n${tones[style] || tones.ouf}\\n\\n`;\n}\n\nexport function buildIntelligencePrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"Intelligence Brief\" : \"Brief d'Intelligence Pro\", isEn ? \"TECHNICAL AUDIT, ARCHITECTURE & STRATEGY\" : \"AUDIT TECHNIQUE, ARCHITECTURE & STRATÉGIE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **Senior Staff Engineer / CTO en free-lance** qui réalise un **Brief d'Intelligence Pro** sur le projet \"${projectName}\". Mission : lire le code comme un pro, écouter ce qu'il dit, et produire un rapport d'audit exceptionnel, ultra-stylé et actionnable. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS == du contexte : cite les chiffres exacts et intègre des extraits de code quand c'est pertinent. Toutes les opportunités et recommandations doivent être cohérentes avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Ne pas imposer de contraintes qui ne sont pas explicitement documentées.${f}\\n\\n## Ton et style (décomplexé, pro, haut de gamme)${banner}\\n- Utilise des émojis pertinents pour chaque section\\n- Des tableaux quand c'est pertinent (stack, dette, modules, concurrents, risques)\\n- Des diagrammes Mermaid pour architecture, data flow et graphe de modules\\n- Des admonitions / citations / encadrés pour les insights clés\\n- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]\\n- Des phrases percutantes, pas de remplissage\\n\\n## Sections obligatoires (sois exhaustif mais concis — NE SAUTE AUCUNE SECTION, numérote exactement de 1 à 11)\\n1. **Executive Summary** : promesse produit + verdict technique en 4 lignes.\\n2. **Stack & Architecture** : framework, runtime, storage, state, build, tests.\\n3. **Tech Radar (Best Tech & Alternatives)** : pour chaque technologie clé, explique POURQUOI c'est le meilleur choix ici (argument massue lié au code), donne une alternative classique et un cas où elle ne serait pas aussi bonne. Sois un avocat de la stack.\\n4. **Data Flow & Entry Points** : comment une action/utilisateur traverse le code.\\n5. **Module Graph & Connexions** : qui appelle quoi, couches, hubs, feuilles.\\n6. **Security & Privacy Posture** : chiffrement, stockage, permissions, vulnérabilités potentielles.\\n7. **Errors, Debt & Smells** : TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, catch vides, etc. Cite les fichiers et lignes.\\n8. **Competitor Landscape** : 3-4 concurrents directs ou indirects de ce type d'app, points forts/différenciants de ${projectName} par rapport à eux.\\n9. **Forces & Risks** : qualité, patterns propres, dette, fragilités.\\n10. **Opportunités** : 3-5 actions concrètes priorisées (refacto, feature, test, perf, sécurité, product). Avant cette section, liste les \"Contraintes produit identifiées\" en début de contexte. Chaque action doit être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet. Si aucune contrainte, explique pourquoi elle est adaptée à la stack/architecture. Exemple : > Justification : Cette action respecte la règle \"no cloud\" en conservant toutes les données en local.\\n11. **Fait avec passion par shinzarou-eng** : une idée créative originale (feature, slogan, concept visuel ou nom de module) inspirée par le code, avec un argument marketing gagnant — dans le respect des contraintes du projet IDENTIFIEES dans le contexte. Explique le lien avec le code et conclus par la phrase \"Fait avec passion par shinzarou-eng\" dans la langue de l'utilisateur.\\n\\nReste factuel, cible les fichiers et symboles par leur chemin relatif. Ne généralise pas hors du contexte fourni. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Sections numérotées de 1 à 11.\\n- [ ] Au moins 3 métriques du contexte citées.\\n- [ ] Au moins 2 extraits de code avec chemin + ligne.\\n- [ ] Chaque opportunité a un \"> Justification :\".\\n- [ ] Aucune section vide.\\n- [ ] Pas de phrase du type \"le code est bien structuré\" sans preuve.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **Senior Staff Engineer / freelance CTO** producing a **Pro Intelligence Brief** for the project \"${projectName}\". Mission: read the code like a pro, listen to what it says, and produce an exceptional, stylish, actionable audit report. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == in the context: cite exact numbers and include code snippets when relevant. All opportunities and recommendations must be consistent with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Do not impose constraints that are not explicitly documented.${f}\\n\\n## Tone & Style (confident, pro, premium)${banner}\\n- Use relevant emojis for each section\\n- Use tables where appropriate (stack, debt, modules, competitors, risks)\\n- Mermaid diagrams for architecture, data flow and module graph\\n- Admonitions / callouts / quote boxes for key insights\\n- Text badges: [CRITICAL], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]\\n- Punchy sentences, no filler\\n\\n## Required Sections (be thorough but concise — DO NOT SKIP ANY SECTION, number them exactly 1 to 11)\\n1. **Executive Summary**: product promise + technical verdict in 4 lines.\\n2. **Stack & Architecture**: framework, runtime, storage, state, build, tests.\\n3. **Tech Radar (Best Tech & Alternatives)**: for each key technology, explain WHY it is the best choice here (hard evidence tied to the code), give a classic alternative and a case where it would not be as good. Be an advocate of the stack.\\n4. **Data Flow & Entry Points**: how an action/user traverses the code.\\n5. **Module Graph & Connections**: who calls what, layers, hubs, leaves.\\n6. **Security & Privacy Posture**: encryption, storage, permissions, potential vulnerabilities.\\n7. **Errors, Debt & Smells**: TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, empty catches, etc. Cite files and lines.\\n8. **Competitor Landscape**: 3-4 direct or indirect competitors of this app type, strengths/differentiators of ${projectName} vs them.\\n9. **Forces & Risks**: quality, unique patterns, debt, fragilities.\\n10. **Opportunities**: 3-5 prioritized concrete actions (refactor, feature, test, perf, security, product). Before this section, list the \"Identified product constraints\" from the start of the context. Each action must be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the \"no cloud\" rule by keeping all data local.\\n11. **Made with passion by shinzarou-eng**: an original creative idea (feature, slogan, visual concept or module name) inspired by the code, with a winning marketing argument — respecting the product constraints IDENTIFIED in the context. Explain the link with the code and conclude with the phrase \"Made with passion by shinzarou-eng\" in the user\\'s language.\\n\\nStay factual, target files and symbols by their relative path. Do not generalize beyond the provided context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Sections numbered 1 to 11.\\n- [ ] At least 3 metrics from the context cited.\\n- [ ] At least 2 code snippets with path + line.\\n- [ ] Each opportunity has a \"> Rationale:\".\\n- [ ] No empty section.\\n- [ ] No sentence like \"the code is well structured\" without proof.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildAuditPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Non-Compliance Audit\" : \"Audit Non-Conformités\", isEn ? \"TECHNICAL DEBT AND RISK SCAN\" : \"SCAN DE LA DETTE TECHNIQUE ET DES RISQUES\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\nTu es un **QA Lead / Staff Engineer** en charge d'un **audit de non-conformités et de dette technique** sur le projet \"${projectName}\". Mission : analyser les signaux fournis, classifier chaque problème, expliquer le risque, et proposer un correctif concret (code ou action).${f}\\n\\n## Ton et style\\n- Utilise des tableaux pour le récapitulatif\\n- Des emojis sévérité : 🔴 Critique / 🟠 Moyen / 🟡 Faible / 🔵 Info\\n- Des badges : [CRITIQUE], [DETTE], [BUG], [FIX], [RECOMMANDATION]\\n- Des blocs de code pour les correctifs\\n- Un encadré visuel de conclusion\\n\\n## Sections obligatoires (numérote exactement)\\n1. **Vue d'ensemble** : nombre total de signaux, répartition par sévérité, verdict global (code sain, dette légère, dette modérée, risque élevé).\\n2. **Tableau des non-conformités** : pour chaque signal, colonnes Fichier:Ligne, Sévérité, Type, Problème, Fix proposé (action immédiate ou code).\\n3. **Top 5 priorités** : les 5 problèmes les plus risqués ou bloquants, avec un snippet de code actuel et un snippet de code corrigé.\\n4. **Plan d'action** : 3-5 tâches concrètes pour nettoyer (par ordre de priorité).\\n5. **Conclusion** : une phrase percutante dans un encadré visuel.\\n\\nReste factuel. Ne généralise pas hors du contexte fourni. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.${banner}`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\nYou are a **QA Lead / Staff Engineer** in charge of a **non-compliance and technical debt audit** for the project \"${projectName}\". Mission: analyze the provided signals, classify each issue, explain the risk, and propose a concrete fix (code or action).${f}\\n\\n## Tone & Style\\n- Use tables for the summary\\n- Severity emojis: 🔴 Critical / 🟠 Medium / 🟡 Low / 🔵 Info\\n- Badges: [CRITICAL], [DEBT], [BUG], [FIX], [RECOMMENDATION]\\n- Code blocks for fixes\\n- A visual conclusion callout\\n\\n## Required Sections (number exactly)\\n1. **Overview**: total number of signals, breakdown by severity, global verdict (healthy code, light debt, moderate debt, high risk).\\n2. **Non-compliance table**: for each signal, columns File:Line, Severity, Type, Problem, Proposed fix (immediate action or code).\\n3. **Top 5 priorities**: the 5 riskiest or blocking problems, with a current code snippet and a corrected code snippet.\\n4. **Action plan**: 3-5 concrete cleanup tasks (in priority order).\\n5. **Conclusion**: a punchy sentence in a visual callout.\\n\\nStay factual. Do not generalize beyond the provided context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.${banner}`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function brandSignature(lang = \"fr\"): string {\n const d = new Date().toISOString().slice(0, 10);\n if (lang === \"en\") {\n return `\\n\\n---\\n\\n> ✨ *Report by **dsh-codebase-chat** v${promptVersion()} — Codebase Analysis — ${d}*\\n> 🔗 *Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.*`;\n }\n return `\\n\\n---\\n\\n> ✨ *Rapport par **dsh-codebase-chat** v${promptVersion()} — Analyse de Codebase — ${d}*\\n> 🔗 *Conçu pour DeepSeek Harness. Extensible à tout agent ou IDE Node.js.*`;\n}\n\nexport function buildAsciiBanner(projectName: string, modeLabel: string, tagline = \"\"): string {\n const raw = (projectName ?? \"\").toUpperCase().replace(/[^A-Z0-9_\\- ]/g, \"\").slice(0, 14);\n const title = raw || \"PROJECT\";\n const ascii = figlet.textSync(title, { font: \"ANSI Shadow\" });\n const lines = ascii.split(\"\\n\").filter((l) => l.trim() !== \"\");\n const subtitle1 = `${modeLabel.toUpperCase()} — ${projectName}`.slice(0, 80);\n const subtitle2 = tagline ? tagline.slice(0, 80) : \"\";\n const width = Math.max(...lines.map((l) => l.length), subtitle1.length, subtitle2.length || 0, 50);\n const pad = (s: string) => s.length < width ? s + \" \".repeat(width - s.length) : s.slice(0, width);\n const h = \"═\".repeat(width + 2);\n const center = (s: string) => {\n const s2 = s.slice(0, width);\n const spaces = Math.max(0, width - s2.length);\n const left = Math.floor(spaces / 2);\n return pad(\" \".repeat(left) + s2);\n };\n const centerArt = (s: string) => center(s);\n\n const blank = pad(\"\");\n\n const body = [\n blank,\n ...lines.map((l) => centerArt(l)),\n blank,\n center(subtitle1),\n subtitle2 ? center(subtitle2) : null,\n blank\n ]\n .filter(Boolean)\n .map((l) => `║ ${l} ║`)\n .join(\"\\n\");\n\n return `╔${h}╗\\n${body}\\n╚${h}╝`;\n}\n\nexport function bannerInstruction(projectName: string, modeLabel: string, tagline = \"\"): string {\n const banner = buildAsciiBanner(projectName, modeLabel, tagline);\n return `\\n\\n${banner}\\n\\n`;\n}\n\nexport function buildReportPrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const signature = brandSignature(lang);\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"Strategic Report\" : \"Rapport Stratégique\", isEn ? \"PROFESSIONAL BOARD-LEVEL ASSESSMENT / EXECUTIVE CTO\" : \"CONSTAT PROFESSIONNEL DE NIVEAU BOARD / EXECUTIVE CTO\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **CTO d'élite / Partner Technique** qui rédige le **Constat Professionnel ultime** sur le projet \"${projectName}\". Ce document doit être le plus beau, le plus percutant, le plus actionnable : un rapport de haut niveau prêt pour un board. Mission : fusionner architecture, dette, concurrence, résultats de tests/build, git, marketing ET respecter les contraintes produit IDENTIFIEES dans le contexte. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS == pour citer des chiffres exacts et insérer des snippets de code. Ne jamais imposer de contraintes qui ne sont pas dans le contexte.${f}\\n\\n## Identité visuelle (obligatoire)${banner}\\n- Utilise des émojis premium pour chaque section\\n- Des tableaux professionnels bordés par des lignes Markdown\\n- Des diagrammes Mermaid\\n- Des encadrés avec > pour les insights et verdicts\\n- Des \"score cards\" : Maturité, Sécurité, Maintenabilité, Performance, UX (notes sur 10 avec justification)\\n- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMANDATION].\\n- Finis par le bloc signature ci-dessous :\\n${signature}\\n\\n## Sections obligatoires (numérote exactement de 1 à 13)\\n1. **Page de Garde** : bannière, date, projet, version, auteur (DSH Codebase Analysis).\\n2. **Executive Summary** : promesse produit, verdict technique, 5 score cards sur 10, argument de pourquoi ce projet peut être le meilleur, et alignement avec les contraintes/produits IDENTIFIEES dans le contexte.\\n3. **Constat Profond** : diagnostic synthétique en 3-5 phrases fortes.\\n4. **SWOT Stratégique** : tableau 2x2 (Forces, Faiblesses, Opportunités, Menaces).\\n5. **Architecture & Tech Radar (Best-of-Breed)** : pour chaque technologie clé, explique pourquoi c'est le meilleur choix ici, donne un argument massue, un contre-argument, et une alternative classique.\\n6. **Module Graph & Connexions** : hubs, feuilles, Mermaid, points de fragilité.\\n7. **Sécurité & Confidentialité** : posture, cryptographie, vulnérabilités.\\n8. **Qualité du Code & Dette** : signaux, top risques, correctifs.\\n9. **Produit & UX** : parcours utilisateur, points de friction, idées d'amélioration.\\n10. **Paysage Concurrentiel** : positionnement vs 3-4 acteurs, avantages différenciants, règles du jeu du marché.\\n11. **Marketing & Positionnement** : persona cible, promesse unique (USP), tagline, canaux d'acquisition, argumentaire \"pourquoi on va gagner\", et **Master Move** : la feature/stratégie dominante qui fait gagner, compatible avec les contraintes du projet IDENTIFIEES dans le contexte.\\n11b. **Contraintes Produits du Projet** (avant la roadmap) : liste les contraintes explicites identifiées dans == CONTRAINTES PRODUIT IDENTIFIEES == en début de contexte. Si aucune, indique \"Aucune contrainte documentée\". Cette section sert de référence pour justifier chaque action.\\n12. **Roadmap 90 Jours & Justifications** : 4-6 actions concrètes priorisées (semaines 1-4, 5-8, 9-12) pour devenir le meilleur. Chaque action DOIT être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet. Si aucune contrainte, explique pourquoi elle est adaptée à la stack/architecture. Exemple : > Justification : Cette action respecte la règle \"100% offline\" car elle n'utilise aucun backend cloud.\\n13. **Fait avec passion par shinzarou-eng** : concept produit/visuel original, slogan percutant, et argumentaire marketing gagnant inspiré par le code — dans le respect des contraintes du projet IDENTIFIEES dans le contexte.\\n\\nReste factuel, cible les fichiers par leur chemin relatif. Ne généralise pas hors du contexte. Si aucune contrainte produit n'est documentée, écris simplement \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Sections numérotées de 1 à 13.\\n- [ ] Bannière ASCII en haut.\\n- [ ] 5 score cards avec notes /10.\\n- [ ] 1 diagramme Mermaid (architecture, data flow ou module graph).\\n- [ ] Chaque action roadmap a un \"> Justification :\".\\n- [ ] Au moins 2 citations de fichiers exactes (ligne).\\n- [ ] Conclusion \"Fait avec passion par shinzarou-eng\".`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are an **elite CTO / Technical Partner** writing the **ultimate Professional Assessment** for the project \"${projectName}\". This document must be the most beautiful, punchy and actionable: a board-ready high-level report. Mission: merge architecture, debt, competition, test/build results, git, marketing AND respect the product constraints IDENTIFIED in the context. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == to cite exact numbers and insert code snippets. Never impose constraints that are not in the context.${f}\\n\\n## Visual Identity (mandatory)${banner}\\n- Use premium emojis for each section\\n- Professional tables framed by Markdown lines\\n- Mermaid diagrams\\n- Quote boxes with > for insights and verdicts\\n- \"Score cards\": Maturity, Security, Maintainability, Performance, UX (scores out of 10 with rationale)\\n- Text badges: [CRITICAL], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMENDATION].\\n- End with the signature block below:\\n${signature}\\n\\n## Required Sections (number exactly 1 to 13)\\n1. **Cover Page**: banner, date, project, version, author (DSH Codebase Analysis).\\n2. **Executive Summary**: product promise, technical verdict, 5 score cards out of 10, argument for why this project can be the best, and alignment with the product constraints IDENTIFIED in the context.\\n3. **Deep Diagnosis**: synthetic diagnosis in 3-5 strong sentences.\\n4. **Strategic SWOT**: 2x2 table (Strengths, Weaknesses, Opportunities, Threats).\\n5. **Architecture & Tech Radar (Best-of-Breed)**: for each key technology, explain why it is the best choice here, give a hard-hitting argument, a counter-argument, and a classic alternative.\\n6. **Module Graph & Connections**: hubs, leaves, Mermaid, fragility points.\\n7. **Security & Privacy**: posture, cryptography, vulnerabilities.\\n8. **Code Quality & Debt**: signals, top risks, fixes.\\n9. **Product & UX**: user journey, friction points, improvement ideas.\\n10. **Competitive Landscape**: positioning vs 3-4 players, differentiating advantages, market rules.\\n11. **Marketing & Positioning**: target persona, unique selling proposition (USP), tagline, acquisition channels, \"why we will win\" argument, and **Master Move**: the dominant feature/strategy that makes you win, compatible with the product constraints IDENTIFIED in the context.\\n11b. **Product Constraints of the Project** (before the roadmap): list the explicit constraints identified in == IDENTIFIED PRODUCT CONSTRAINTS == at the start of the context. If none, indicate \"No documented constraints\". This section serves as a reference to justify each action.\\n12. **90-Day Roadmap & Rationale**: 4-6 prioritized concrete actions (weeks 1-4, 5-8, 9-12) to become the best. Each action MUST be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the \"100% offline\" rule by not using any cloud backend.\\n13. **Made with passion by shinzarou-eng**: an original product/visual concept, a punchy slogan, and a winning marketing argument inspired by the code — respecting the product constraints IDENTIFIED in the context.\\n\\nStay factual, target files by their relative path. Do not generalize beyond the context. If no product constraints are documented, simply write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Sections numbered 1 to 13.\\n- [ ] ASCII banner at the top.\\n- [ ] 5 score cards with scores out of 10.\\n- [ ] 1 Mermaid diagram (architecture, data flow or module graph).\\n- [ ] Each roadmap action has a \"> Rationale:\".\\n- [ ] At least 2 exact file citations (line).\\n- [ ] Conclusion \"Made with passion by shinzarou-eng\".`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildTasksPrompt(context: string, projectName: string, focus = \"\", style = \"punchy\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(style, lang);\n const banner = bannerInstruction(projectName, isEn ? \"TASKS Action Plan\" : \"Plan d'Action TASKS\", isEn ? \"EXECUTABLE ROADMAP AND PRIORITIZED SPRINTS\" : \"ROADMAP EXÉCUTABLE ET SPRINTS PRIORISÉS\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **Delivery Lead / CTO** qui transforme un rapport de codebase en **plan d'action exécutable** pour le projet \"${projectName}\". RÈGLE D'OR : la section == TÂCHES GÉNÉRÉES DEPUIS LES SIGNAUX == contient déjà les tâches avec leurs blocs Avant/Après. Tu DOIS les recopier TELLES QUELLES dans le TASKS.md final, les organiser en sprints (P0, P1, P2, P3), et conserver OBLIGATOIREMENT les blocs Avant et Après FOURNIS. Tu as le droit d'ajouter 2-3 tâches maximum si tu identifies un risque majeur absent, mais la majorité du plan doit venir des tâches pré-générées. Chaque tâche doit être compatible avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Avant la liste des tâches, ajoute une section \"Contraintes produit identifiées\" pour servir de référence.${f}\\n\\n## Ton et style${banner}\\n- Un titre clair :\\n~~~markdown\\n# TASKS.md — Plan d'action ${projectName}\\n~~~\\n- Des tableaux avec colonnes : Priorité, Tâche, Fichier(s) concerné(s), Difficulté (1-5), Impact, Livrable\\n- Des checklists Markdown : '[ ]' / '[x]'\\n- Des sprints : Sprint 1 (semaines 1-2), Sprint 2, Sprint 3\\n- Des badges : [CRITIQUE], [RAPIDE], [STRATEGIQUE], [TECH-DEBT].\\n- Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)\\n\\n## Sections obligatoires\\n1. **Vue d'ensemble** : 3-5 tâches prioritaires dans un tableau.\\n2. **Sprint 1 — Fondations** : sécurité, stabilité, tests.\\n3. **Sprint 2 — Amélioration** : refacto, UX, performance.\\n4. **Sprint 3 — Différenciation** : features gagnantes, marketing.\\n5. **Checklist globale** : toutes les tâches avec '[ ]'.\\n\\nChaque tâche doit être actionnable, citer un chemin de fichier relatif quand c'est possible, et être suivie d'une phrase commençant par \"> Justification :\" qui explique pourquoi elle est cohérente avec les règles du projet.\\n\\n## Exigence AVANT / APRÈS\\nPour CHAQUE tâche, ajoute obligatoirement deux blocs de code :\\n- **Avant** : extrait du code actuel (max 10 lignes) depuis le contexte == TECH DEBT & SIGNALS == ou == EXTRAITS DE CODE CLÉS ==.\\n- **Après** : extrait du code corrigé proposé (max 10 lignes).\\n\\nExemple de format :\\n- [ ] **[TASK-01] Typer l'événement SpeechRecognition**\\n - Fichier : src/components/KodaAssistantModal.tsx:651\\n - Avant :\\n --- code ts ---\\n recognition.onresult = (event: any) => { ... };\\n ---\\n - Après :\\n --- code ts ---\\n recognition.onresult = (event: SpeechRecognitionEvent) => { ... };\\n ---\\n > Justification : ...\\n\\nSi tu ne peux pas extraire l'extrait, cite au minimum le fichier et la ligne.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] 5 sections présentes (Vue d'ensemble, Sprint 1, Sprint 2, Sprint 3, Checklist globale).\\n- [ ] Toutes les tâches ont un statut '[ ]'.\\n- [ ] Chaque tâche a un bloc **Avant** (code actuel) et un bloc **Après** (code proposé), ou 'N/A' avec explication.\\n- [ ] Chaque tâche a un Fichier:Ligne.\\n- [ ] Chaque tâche a un \"> Justification :\".\\n- [ ] Conclusion \"Fait avec passion par shinzarou-eng\".\\n\\nSi aucune contrainte n'est trouvée, écris \"Contraintes produit : aucune\" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **Delivery Lead / CTO** turning a codebase report into an **executable action plan** for the project \"${projectName}\". GOLDEN RULE: the section == TASKS GENERATED FROM SIGNALS == already contains the tasks with their Before/After blocks. You MUST copy them AS-IS into the final TASKS.md, organize them into sprints (P0, P1, P2, P3), and OBLIGATORILY keep the provided Before and After blocks. You may add 2-3 extra tasks at most if you identify a major missing risk, but the majority of the plan must come from the pre-generated tasks. Each task must be compatible with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Before the task list, add an \"Identified product constraints\" section as a reference.${f}\\n\\n## Tone & Style${banner}\\n- A clear title:\\n~~~markdown\\n# TASKS.md — Action Plan ${projectName}\\n~~~\\n- Tables with columns: Priority, Task, Concerned file(s), Difficulty (1-5), Impact, Deliverable\\n- Markdown checklists: '[ ]' / '[x]'\\n- Sprints: Sprint 1 (weeks 1-2), Sprint 2, Sprint 3\\n- Badges: [CRITICAL], [QUICK], [STRATEGIC], [TECH-DEBT].\\n- Conclude with: Made with passion by shinzarou-eng (in the user\\'s language)\\n\\n## Required Sections\\n1. **Overview**: 3-5 prioritized tasks in a table.\\n2. **Sprint 1 — Foundations**: security, stability, tests.\\n3. **Sprint 2 — Improvement**: refactor, UX, performance.\\n4. **Sprint 3 — Differentiation**: winning features, marketing.\\n5. **Global Checklist**: all tasks with '[ ]'.\\n\\nEach task must be actionable, cite a relative file path when possible, and be followed by a sentence starting with \"> Rationale:\" explaining why it is consistent with the project rules.\\n\\n## BEFORE / AFTER Requirement\\nFor EACH task, you MUST add two code blocks:\\n- **Before**: current code snippet (max 10 lines) from == TECH DEBT & SIGNALS == or == KEY CODE SNIPPETS == in the context.\\n- **After**: proposed fixed code snippet (max 10 lines).\\n\\nExample format:\\n- [ ] **[TASK-01] Type the SpeechRecognition event**\\n - File: src/components/KodaAssistantModal.tsx:651\\n - Before:\\n --- code ts ---\\n recognition.onresult = (event: any) => { ... };\\n ---\\n - After:\\n --- code ts ---\\n recognition.onresult = (event: SpeechRecognitionEvent) => { ... };\\n ---\\n > Rationale : ...\\n\\nIf you cannot extract the snippet, at least cite the file and line.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] 5 sections present (Overview, Sprint 1, Sprint 2, Sprint 3, Global Checklist).\\n- [ ] All tasks have status '[ ]'.\\n- [ ] Each task has a **Before** (current code) and an **After** (proposed code) block, or 'N/A' with explanation.\\n- [ ] Each task has a File:Line.\\n- [ ] Each task has a \"> Rationale:\".\\n- [ ] Conclusion \"Made with passion by shinzarou-eng\".\\n\\nIf no constraints are found, write \"Product constraints: none\" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildCeoPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const styleText = styleInstruction(\"ouf\", lang);\n const signature = brandSignature(lang);\n const banner = bannerInstruction(projectName, isEn ? \"One-Page CEO Brief\" : \"One-Page CEO Brief\", isEn ? \"EXECUTIVE SUMMARY FOR DECISION MAKERS\" : \"EXECUTIVE SUMMARY POUR DÉCIDEUR\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}Tu es un **CTO / CEO / Partner** qui rédige le **One-Page Executive Brief** ultime sur le projet \"${projectName}\". RÈGLE D'OR : ce document tient sur UNE SEULE PAGE A4. MAXIMUM 7 sections courtes. Pas de blabla, que des insights à fort impact, des chiffres, des verdicts, des actions. Chaque section max 5-8 lignes. Utilise tableaux et listes. Si tu dépasses une page, tu as échoué.${f}\\n\\n## Identité visuelle (obligatoire)${banner}\\n- Tableau exécutif unique avec les metrics clés.\\n- 5 score cards (sur 10) avec justification en UNE phrase.\\n- Encadrés visuels pour les insights.\\n- Badges : [CRITIQUE], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].\\n- Conclus par le bloc signature ci-dessous :\\n${signature}\\n\\n## Sections obligatoires (numérote de 1 à 7, STRICTEMENT 1 PAGE)\\n1. **Bannière & Titre** : 1 ligne.\\n2. **Executive Summary** : 3 phrases + 1 tableau 4 métriques.\\n3. **Verdict du board** : 5 score cards, 1 ligne chacune (Domaine | Note | 5 mots de justification).\\n4. **Top 3 risques / dette** : 1 ligne par risque (Fichier:Ligne - Problème - Impact).\\n5. **Top 3 opportunités / Killer Moves** : 1 phrase par action + Justification en 1 phrase.\\n6. **SWOT ultra-concis** : 4 cases, max 4 points de 3-5 mots chacun.\\n7. **Fait avec passion par shinzarou-eng** : 1 concept + 1 slogan + 1 phrase marketing.\\n\\nReste factuel, cible les fichiers par leur chemin relatif. Exploite les == MÉTRIQUES PROJET == et == EXTRAITS DE CODE CLÉS ==. Réponds dans la langue de l'utilisateur.\\n\\n## CHECKLIST FINALE (obligatoire, vérifie avant d'envoyer)\\n- [ ] Exactement 7 sections numérotées.\\n- [ ] Le document tient sur une page (max 60-80 lignes au total).\\n- [ ] 5 score cards, 1 ligne chacune.\\n- [ ] Top 3 risques avec Fichier:Ligne.\\n- [ ] Top 3 opportunités avec \"> Justification :\".\\n- [ ] SWOT : 4 points de 3-5 mots par case.\\n- [ ] Aucun Mermaid, aucun tableau géant, aucune explication longue.`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${styleText}You are a **CTO / CEO / Partner** writing the ultimate **One-Page Executive Brief** for the project \"${projectName}\". GOLDEN RULE: this document fits on a SINGLE A4 page. MAXIMUM 7 short sections. No filler, only high-impact insights, numbers, verdicts, actions. Each section max 5-8 lines. Use tables and lists. If you exceed one page, you failed.${f}\\n\\n## Visual Identity (mandatory)${banner}\\n- Single executive table with key metrics.\\n- 5 score cards (out of 10) with rationale in ONE sentence.\\n- Visual callouts for insights.\\n- Badges: [CRITICAL], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].\\n- Conclude with the signature block below:\\n${signature}\\n\\n## Required Sections (number 1 to 7, STRICTLY 1 PAGE)\\n1. **Banner & Title**: 1 line.\\n2. **Executive Summary**: 3 sentences + 1 table with 4 metrics.\\n3. **Board verdict**: 5 score cards, 1 line each (Area | Score | 5-word rationale).\\n4. **Top 3 risks / debt**: 1 line per risk (File:Line - Problem - Impact).\\n5. **Top 3 opportunities / Killer Moves**: 1 sentence per action + Rationale in 1 sentence.\\n6. **Ultra-concise SWOT**: 4 boxes, max 4 points of 3-5 words each.\\n7. **Made with passion by shinzarou-eng**: 1 concept + 1 slogan + 1 marketing sentence.\\n\\nStay factual, target files by their relative path. Leverage == PROJECT METRICS == and == KEY CODE SNIPPETS ==. Respond in the user\\'s language.\\n\\n## FINAL CHECKLIST (mandatory, verify before sending)\\n- [ ] Exactly 7 numbered sections.\\n- [ ] Document fits on one page (max 60-80 lines total).\\n- [ ] 5 score cards, 1 line each.\\n- [ ] Top 3 risks with File:Line.\\n- [ ] Top 3 opportunities with \"> Rationale:\".\\n- [ ] SWOT: 4 points of 3-5 words per box.\\n- [ ] No Mermaid, no giant table, no long explanation.`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildBuildPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Build Benchmark\" : \"Build Benchmark\", isEn ? \"BUILD PERFORMANCE & BUNDLE\" : \"PERFORMANCE DE BUILD & BUNDLE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **Staff Engineer / Build Performance Expert**. Analyse le résultat du build du projet \"${projectName}\". Produis un rapport ultra-concis et percutant.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"BUILD BENCHMARK — ${(projectName ?? \"\").toUpperCase()}\"\\n- 3 score cards : Vitesse, Taille du bundle, Stabilité (notes /10)\\n- Tableau des fichiers de sortie (nom, taille)\\n- Top 3 leviers d'optimisation\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **Staff Engineer / Build Performance Expert**. Analyze the build result of the project \"${projectName}\". Produce an ultra-concise, punchy report.${f}\\n\\n## Expected format\\n- ASCII banner: \"BUILD BENCHMARK — ${(projectName ?? \"\").toUpperCase()}\"\\n- 3 score cards: Speed, Bundle size, Stability (scores out of 10)\\n- Output files table (name, size)\\n- Top 3 optimization levers\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildPlayerPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Player Brief\" : \"Player Brief\", isEn ? \"USER JOURNEY & EXPERIENCE\" : \"PARCOURS UTILISATEUR & EXPÉRIENCE\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **UX Researcher / Playtester / Product Hunter** qui réalise un **Player Brief** sur le projet \"${projectName}\". Tu ne regardes pas le code comme un dev, mais comme un vrai utilisateur final qui découvre l'app, clique, se frustre, se réjouit. Mission : décrire l'expérience vécue, identifier les moments clés, les frictions et les opportunités de 'wow'.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"PLAYER BRIEF — ${(projectName ?? \"\").toUpperCase()}\"\\n- Score cards : Onboarding, Clarté, Réactivité, Confiance, Plaisir (sur 10)\\n- Tableau du parcours utilisateur : Étape, Action, Sentiment, Friction, Fix\\n- Top 5 moments 'Wow' (ce qui impressionne)\\n- Top 5 frictions bloquantes ou irritantes\\n- Idées de gamification / engagement (si pertinent)\\n- Roadmap UX 30 jours : 3 actions rapides d'impact utilisateur\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **UX Researcher / Playtester / Product Hunter** producing a **Player Brief** for the project \"${projectName}\". You do not look at the code like a dev, but like a real end user discovering the app, clicking, getting frustrated, getting delighted. Mission: describe the lived experience, identify key moments, frictions and 'wow' opportunities.${f}\\n\\n## Expected format\\n- ASCII banner: \"PLAYER BRIEF — ${(projectName ?? \"\").toUpperCase()}\"\\n- Score cards: Onboarding, Clarity, Responsiveness, Trust, Delight (out of 10)\\n- User journey table: Step, Action, Sentiment, Friction, Fix\\n- Top 5 'Wow' moments (what impresses)\\n- Top 5 blocking or annoying frictions\\n- Gamification / engagement ideas (if relevant)\\n- 30-day UX roadmap: 3 quick high-impact actions\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildGitPrompt(context: string, projectName: string, focus = \"\", lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const f = focus ? (isEn ? `\\nRequested focus: ${focus}` : `\\nFocus demandé : ${focus}`) : \"\";\n const banner = bannerInstruction(projectName, isEn ? \"Git Intelligence\" : \"Git Intelligence\", isEn ? \"HISTORY, HOTSPOTS & RISKS\" : \"HISTORIQUE, HOTSPOTS & RISQUES\");\n const fr = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nTu es un **Tech Lead** qui analyse l'historique git du projet \"${projectName}\". Résume l'activité, identifie les tendances, les hotspots de modification et les risques récents.${f}\\n\\n## Format attendu\\n- Bannière ASCII : \"GIT INTELLIGENCE — ${(projectName ?? \"\").toUpperCase()}\"\\n- Derniers commits synthétisés\\n- Hotspots (fichiers qui bougent le plus)\\n- Risques récents\\n- Suggestions de prochaines actions\\n- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;\n const en = `${context}\\n\\n${langInstruction(lang)}\\n\\n${banner}\\n\\nYou are a **Tech Lead** analyzing the git history of the project \"${projectName}\". Summarize activity, identify trends, modification hotspots and recent risks.${f}\\n\\n## Expected format\\n- ASCII banner: \"GIT INTELLIGENCE — ${(projectName ?? \"\").toUpperCase()}\"\\n- Synthesized recent commits\\n- Hotspots (files that change the most)\\n- Recent risks\\n- Suggested next actions\\n- Conclusion: Made with passion by shinzarou-eng (user language)`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nexport function buildApplyPrompt(filePath: string, newContent: string, projectName: string, lang = \"fr\"): string {\n const isEn = lang === \"en\";\n const fr = `Applique la mise à jour suivante au fichier \"${filePath}\" du projet \"${projectName}\".\\n\\n${langInstruction(lang)}\\n\\nTu es un **Staff Engineer**. Le contenu fourni est la nouvelle version complète du fichier. Réponds UNIQUEMENT par :\\n\\n- Si le patch semble correct : \"Fichier ${filePath} mis à jour avec succès.\"\\n- Si tu refuses : dis pourquoi en une phrase.\\n\\nFait avec passion par shinzarou-eng.\\n\\n---\\n\\nNouveau contenu :\\n~~~\\n${newContent.slice(0, 8000)}\\n~~~`;\n const en = `Apply the following update to file \"${filePath}\" in project \"${projectName}\".\\n\\n${langInstruction(lang)}\\n\\nYou are a **Staff Engineer**. The provided content is the complete new version of the file. Respond ONLY with:\\n\\n- If the patch looks correct: \"File ${filePath} updated successfully.\"\\n- If you refuse: say why in one sentence.\\n\\nMade with passion by shinzarou-eng.\\n\\n---\\n\\nNew content:\\n~~~\\n${newContent.slice(0, 8000)}\\n~~~`;\n return withCitations(isEn ? en : fr, lang);\n}\n\nconst TOOL_BUILDERS: Record<string, (o: Required<Pick<ToolPromptOptions, 'context' | 'projectName'>> & ToolPromptOptions) => string> = {\n codebase_intelligence: (o) => buildIntelligencePrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_report: (o) => buildReportPrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_audit: (o) => buildAuditPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_tasks: (o) => buildTasksPrompt(o.context, o.projectName, o.focus || o.query || '', o.style || 'ouf', o.lang || 'fr'),\n codebase_ceo: (o) => buildCeoPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_player: (o) => buildPlayerPrompt(o.context, o.projectName, o.focus || o.query || '', o.lang || 'fr'),\n codebase_search: (o) => buildSearchPrompt(o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_explain: (o) => buildExplainPrompt(o.filePath || o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_refactor: (o) => buildRefactorPrompt(o.filePath || o.focus || '', o.description || o.query || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_chat: (o) => buildChatPrompt(o.query || o.focus || '', o.context, o.projectName, o.crea, o.creaTheme, o.lang || 'fr'),\n codebase_crea: (o) => buildCreaPrompt(o.focus || o.query || 'creative idea', o.context, o.projectName, o.lang || 'fr'),\n};\n\n/**\n * Assemble the full LLM prompt (context + persona + mandatory sections +\n * ASCII banner + citation rules) for a codebase_* tool — the same text the\n * DeepSeek Harness plugin sends, so MCP clients and the CLI get identical\n * reports. Unknown tool names throw.\n */\nexport function buildToolPrompt(tool: string, opts: ToolPromptOptions): string {\n const builder = TOOL_BUILDERS[tool];\n if (!builder) throw new Error(`unknown prompt tool: ${tool}`);\n return normalizeLabels(builder(opts), opts.lang || 'fr');\n}\n","// Embedded local LLM — a small GGUF model served by node-llama-cpp, downloaded\n// into the shared cache dir on first use. Enables fully-offline answers with\n// no API key and no host model. Quality is limited vs hosted models, so it is\n// opt-in via CODEBASE_LOCAL_LLM, the `localLlm` tool argument or `--local`.\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getCacheDir } from './project.js';\n\n// Small instruct model (~1 GB, CPU-friendly). Override with CODEBASE_LOCAL_LLM\n// set to an `hf:owner/repo:QUANT` URI or an absolute path to a .gguf file.\nconst DEFAULT_MODEL_URI = 'hf:Qwen/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M';\nconst LOCAL_CONTEXT_SIZE = 8192;\nconst LOCAL_MAX_TOKENS = 1536;\n\nexport function isLocalLlmEnabled(): boolean {\n return !!(process.env.CODEBASE_LOCAL_LLM || '').trim();\n}\n\nfunction configuredModel(): string {\n const v = (process.env.CODEBASE_LOCAL_LLM || '').trim();\n if (!v || v === '1' || v.toLowerCase() === 'true') return DEFAULT_MODEL_URI;\n return v;\n}\n\nasync function importLlama(): Promise<any> {\n try {\n return await import('node-llama-cpp');\n } catch {\n throw new Error('Local LLM needs the optional dependency: npm i node-llama-cpp');\n }\n}\n\nlet modelPromise: Promise<any> | null = null;\n\nfunction loadLocalModel(): Promise<any> {\n if (!modelPromise) {\n modelPromise = (async () => {\n const spec = configuredModel();\n let modelPath = spec;\n if (spec.startsWith('hf:')) {\n const { createModelDownloader } = await importLlama();\n const downloader = await createModelDownloader({\n modelUri: spec,\n dirPath: join(getCacheDir(), 'models'),\n });\n modelPath = await downloader.download();\n } else if (!existsSync(spec)) {\n throw new Error(`Local model not found: ${spec}`);\n }\n const { getLlama } = await importLlama();\n const cpuOnly = /^(0|off|false|cpu)$/i.test(process.env.CODEBASE_LOCAL_GPU || '');\n const llama = await getLlama(cpuOnly ? { gpu: false } : {});\n try {\n return await llama.loadModel({ modelPath });\n } catch (err) {\n // GPU backends (CUDA/VRAM) can fail on smaller cards — retry on CPU.\n if (cpuOnly) throw err;\n console.error(`[local-llm] GPU load failed (${err instanceof Error ? err.message : err}) — falling back to CPU. Slower, but works. Set CODEBASE_LOCAL_GPU=off to skip GPU entirely.`);\n const cpuLlama = await getLlama({ gpu: false });\n return cpuLlama.loadModel({ modelPath });\n }\n })();\n modelPromise.catch(() => { modelPromise = null; });\n }\n return modelPromise;\n}\n\nexport async function callLocalLlm(prompt: string, lang = 'fr'): Promise<string> {\n const model = await loadLocalModel();\n const { LlamaChatSession } = await importLlama();\n const context = await model.createContext({ contextSize: LOCAL_CONTEXT_SIZE });\n try {\n const session = new LlamaChatSession({\n contextSequence: context.getSequence(),\n systemPrompt: lang === 'en'\n ? 'You are a senior codebase analyst. Be precise and cite files with [source: path:line].'\n : 'Tu es un analyste codebase senior. Sois precis et cite les fichiers avec [source: chemin:ligne].',\n });\n return await session.prompt(prompt, {\n temperature: 0.2,\n maxTokens: LOCAL_MAX_TOKENS,\n // Small models degenerate into loops at low temperature — penalize\n // repeated tokens so the answer moves forward instead of echoing.\n repeatPenalty: { lastTokens: 128, penalty: 1.2, penalizeNewLine: false },\n });\n } finally {\n await context.dispose();\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","sep","join","extname","join","relative","sep","readFile","extname","relative","sep","readFile","join","score","t","basename","readFile","join","basename","readFile","join","t","t","existsSync","join","join","existsSync"]}