@ajdev0/token-shrink 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser/registry.ts","../src/cli.ts","../src/server/assembler.ts","../src/watcher/sync.ts","../src/parser/pruner.ts","../src/parser/wasm.ts"],"sourcesContent":["/**\n * Language registry mapping file extensions to tree-sitter grammars and\n * pruning strategies. Each spec defines:\n * - the web-tree-sitter language name\n * - the `.wasm` file and the authoritative download URL\n * - one or more S-expression queries (the \"prune query\") that match the\n * implementation blocks to remove, plus the replacement token.\n *\n * The empty-query default of '' matches nothing, so the pruner leaves the\n * file untouched when a language has no registered prune rules yet.\n */\n\nimport path from 'node:path';\n\n/** Source of truth mirror in the PRD language matrix. */\nexport type Replacement = {\n /** Token used to replace a pruned block. */\n token: string;\n /**\n * Optional regex, run against the raw block text. If it matches, the block\n * is kept instead of pruned. Used to preserve directive/header lines\n * ('use client/server') even when they live inside an otherwise-pruned body.\n */\n keepIf?: RegExp;\n};\n\nexport interface LanguageSpec {\n /** Friendly name, used in logs and the report header. */\n name: string;\n /** web-tree-sitter `Language.load` file name. */\n wasm: string;\n /** Where to download the `.wasm` binary if not cached locally. */\n url: string;\n /** Extensions that map to this language: `.ts`, `.tsx`, etc. */\n extensions: string[];\n /**\n * One or more (query, replacement) pairs. Blocks matched by each query are\n * pruned bottom-up. Queries are combined; a block is pruned if it matches\n * any. This keeps small, frequently repeated constructs cheap to configure.\n */\n rules: { query: string; replacement: Replacement }[];\n}\n\n// ---------------------------------------------------------------------------\n// Pruning workhorse: prune every `statement_block` / `block` node.\n// ---------------------------------------------------------------------------\n\nconst BLOCK = { query: '(statement_block) @block', replacement: { token: '/* ... */' } };\nconst SWIFT_BLOCK = { query: '(statements) @block', replacement: { token: '/* ... */' } };\nconst GO_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst RUST_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst PY_BLOCK = { query: '(block) @block', replacement: { token: 'pass' } };\nconst C_BLOCK = { query: '(compound_statement) @block', replacement: { token: '/* ... */' } };\nconst JAVA_BLOCK = {\n query: '(block) @block',\n replacement: { token: '/* ... */' },\n};\nconst PHP_BLOCK = {\n query: '(compound_statement) @block',\n replacement: { token: '/* ... */' },\n};\nconst KOTLIN_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst DART_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\n\n// Keeps `'use client'`/`'use server'` and top-level directive strings.\nconst DIRECTIVE_KEEP: Replacement = {\n token: '/* ... */',\n keepIf: /^\\s*'use (client|server)'/,\n};\n\nexport const registry: Record<string, LanguageSpec> = {\n typescript: {\n name: 'TypeScript',\n wasm: 'tree-sitter-typescript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-typescript/releases/latest/download/tree-sitter-typescript.wasm',\n extensions: ['.ts', '.cts', '.mts'],\n rules: [BLOCK],\n },\n javascript: {\n name: 'JavaScript',\n wasm: 'tree-sitter-javascript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-javascript/releases/latest/download/tree-sitter-javascript.wasm',\n extensions: ['.js', '.cjs', '.mjs'],\n rules: [BLOCK],\n },\n tsx: {\n name: 'React / Next.js (TSX)',\n wasm: 'tree-sitter-tsx.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-typescript/releases/latest/download/tree-sitter-tsx.wasm',\n extensions: ['.tsx'],\n rules: [{ query: '(statement_block) @block', replacement: DIRECTIVE_KEEP }],\n },\n jsx: {\n name: 'React (JSX)',\n wasm: 'tree-sitter-javascript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-javascript/releases/latest/download/tree-sitter-javascript.wasm',\n extensions: ['.jsx'],\n rules: [{ query: '(statement_block) @block', replacement: DIRECTIVE_KEEP }],\n },\n python: {\n name: 'Python',\n wasm: 'tree-sitter-python.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-python/releases/latest/download/tree-sitter-python.wasm',\n extensions: ['.py', '.pyi'],\n rules: [PY_BLOCK],\n },\n dart: {\n name: 'Dart / Flutter',\n wasm: 'tree-sitter-dart.wasm',\n url: 'https://github.com/UserNobody14/tree-sitter-dart.wasm/releases/latest/download/tree-sitter-dart.wasm',\n extensions: ['.dart'],\n rules: [DART_BLOCK],\n },\n swift: {\n name: 'Swift / SwiftUI',\n wasm: 'tree-sitter-swift.wasm',\n url: 'https://github.com/alex-pinkus/tree-sitter-swift/releases/latest/download/tree-sitter-swift.wasm',\n extensions: ['.swift'],\n rules: [SWIFT_BLOCK],\n },\n go: {\n name: 'Go',\n wasm: 'tree-sitter-go.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-go/releases/latest/download/tree-sitter-go.wasm',\n extensions: ['.go'],\n rules: [GO_BLOCK],\n },\n rust: {\n name: 'Rust',\n wasm: 'tree-sitter-rust.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-rust/releases/latest/download/tree-sitter-rust.wasm',\n extensions: ['.rs'],\n rules: [RUST_BLOCK],\n },\n java: {\n name: 'Java',\n wasm: 'tree-sitter-java.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-java/releases/latest/download/tree-sitter-java.wasm',\n extensions: ['.java'],\n rules: [JAVA_BLOCK],\n },\n kotlin: {\n name: 'Kotlin',\n wasm: 'tree-sitter-kotlin.wasm',\n url: 'https://github.com/fwcd/tree-sitter-kotlin/releases/latest/download/tree-sitter-kotlin.wasm',\n extensions: ['.kt', '.kts'],\n rules: [KOTLIN_BLOCK],\n },\n c: {\n name: 'C',\n wasm: 'tree-sitter-c.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-c/releases/latest/download/tree-sitter-c.wasm',\n extensions: ['.c', '.h'],\n rules: [C_BLOCK],\n },\n cpp: {\n name: 'C++',\n wasm: 'tree-sitter-cpp.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-cpp/releases/latest/download/tree-sitter-cpp.wasm',\n extensions: ['.cc', '.cpp', '.cxx', '.hpp', '.hh', '.hxx'],\n rules: [C_BLOCK],\n },\n php: {\n name: 'PHP',\n wasm: 'tree-sitter-php.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-php/releases/latest/download/tree-sitter-php.wasm',\n extensions: ['.php'],\n rules: [PHP_BLOCK],\n },\n} satisfies Record<string, LanguageSpec>;\n\n/** Map of extension -> language spec id, built once. */\nconst extensionIndex = new Map<string, string>();\nfor (const [id, spec] of Object.entries(registry)) {\n for (const ext of spec.extensions) {\n extensionIndex.set(ext, id);\n }\n}\n\nexport type LanguageId = keyof typeof registry;\n\n/** Return the language spec for a file path, or null if unsupported. */\nexport function languageForFile(filePath: string): LanguageSpec | null {\n const langId = extensionIndex.get(path.extname(filePath).toLowerCase());\n if (!langId) return null;\n return registry[langId];\n}\n\n/** All languages that have at least one prune rule. */\nexport const supportedLanguageIds = Object.keys(registry) as LanguageId[];\n\n/** Convenience: list every known extension. */\nexport const allExtensions = [...extensionIndex.keys()];\n","/**\n * HTTP/CLI server. Exposes the context assembler as a small Fastify service:\n *\n * GET /health -> liveness\n * POST /v1/context -> { activeFilePath, maxSkeletons?, includeStats? } => markdown\n *\n * Run as `token-shrink` or `node dist/cli.js`. The server watches `--root`\n * (defaults to cwd) and keeps the import graph + skeletons warm.\n */\n\nimport Fastify from 'fastify';\nimport picocolors from 'picocolors';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { assemble } from './server/assembler.js';\nimport { createWatcher, type Matcher } from './watcher/sync.js';\nimport { warmGrammars } from './parser/wasm.js';\n\nexport interface CliOptions {\n port?: number;\n host?: string;\n root?: string;\n ignored?: Matcher[];\n silent?: boolean;\n}\n\nfunction parseArgv(argv = process.argv): Record<string, string> {\n const out: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const cur = argv[i];\n if (cur?.startsWith('--')) {\n const key = cur.slice(2);\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n out[key] = next;\n i++;\n } else {\n out[key] = 'true';\n }\n }\n }\n return out;\n}\n\n/** Start the Fastify server; returns the running instance + watcher handle. */\nexport async function startServer(opts: CliOptions = {}) {\n const args = parseArgv();\n const port = opts.port ?? Number(args.port ?? process.env.PORT ?? 3000);\n const host = opts.host ?? args.host ?? '0.0.0.0';\n const root = path.resolve(opts.root ?? args.root ?? process.cwd());\n const silent = opts.silent ?? args.silent === 'true';\n\n const log = (msg: string) => {\n if (!silent) console.log(picocolors.dim(msg));\n };\n\n // Warm grammars in the background so the first prune isn't slow.\n void warmGrammars().catch(() => {});\n\n const watcher = createWatcher({ root, ignored: opts.ignored });\n log(`Indexing ${root} in the background…`);\n void watcher.indexAll().then((n) => log(`Indexed ${n} files.`));\n\n const app = Fastify({ logger: !silent });\n\n app.get('/health', async () => ({\n status: 'ok',\n service: 'token-shrink',\n version: '2.0.0',\n root,\n indexed: watcher.cache.entries.size,\n }));\n\n app.post('/v1/context', async (req, reply) => {\n const body = (req.body ?? {}) as {\n activeFilePath?: string;\n maxSkeletons?: number;\n includeStats?: boolean;\n };\n if (!body.activeFilePath) {\n return reply.status(400).send({ error: '`activeFilePath` is required' });\n }\n const result = assemble(body.activeFilePath, watcher.cache.entries, {\n maxSkeletons: body.maxSkeletons,\n includeStats: body.includeStats,\n });\n return {\n markdown: result.markdown,\n activeFilePath: result.activeFilePath,\n dependencies: result.included.map((i) => i.filePath),\n unresolved: result.unresolved,\n };\n });\n\n app.setNotFoundHandler(async (req, reply) => {\n void req;\n return reply.status(404).send({ error: 'Not found' });\n });\n\n await app.listen({ port, host });\n log(`Listening on http://${host}:${port}`);\n\n return { app, watcher };\n}\n\n// Start when invoked directly (`node dist/cli.cjs` / the `token-shrink` bin),\n// not when imported as a library. `realpathSync` resolves the npm bin symlink,\n// so `token-shrink` -> `dist/cli.cjs` is detected as `cli.cjs`.\nconst argv1 = process.argv[1] ? path.basename(process.argv[1]) : '';\nlet argv1Real = '';\ntry {\n argv1Real = process.argv[1]\n ? path.basename(fs.realpathSync(process.argv[1]))\n : '';\n} catch {\n /* path may not exist yet (tsx/dev runners) — fall back to argv basename */\n}\nif (\n argv1 === 'cli.js' || argv1 === 'cli.mjs' ||\n argv1 === 'cli.cjs' || argv1 === 'cli.ts' ||\n argv1Real === 'cli.js' || argv1Real === 'cli.mjs' ||\n argv1Real === 'cli.cjs' || argv1Real === 'cli.ts'\n) {\n startServer().catch((err) => {\n console.error(picocolors.red(`[token-shrink] ${err.message}`));\n process.exitCode = 1;\n });\n}\n","/**\n * Context Assembler (Phase 4). Produces a Markdown context payload from the\n * graph cache:\n *\n * Ring 0 — the active file's raw, full text.\n * Ring 1 — pruned skeletons of the files it directly imports.\n *\n * The payload keeps full type signatures (imports, interfaces, exports) while\n * dropping implementation bodies, delivering the 80–90% reduction target.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { GraphCache } from '../watcher/sync.js';\n\nexport interface AssembleOptions {\n /** Number of PRD-style stats to append (disabled by default). */\n includeStats?: boolean;\n /** Maximum number of ring-1 files to include. */\n maxSkeletons?: number;\n /** Whether the active file itself should also be pruned (Ring 0 raw by default). */\n pruneActiveFile?: boolean;\n}\n\nexport interface AssembleResult {\n /** Human-readable Markdown payload for an agent. */\n markdown: string;\n activeFilePath: string;\n /** Ring-0 full text of the active file. */\n activeSource: string;\n /** Ring-1 entries actually included. */\n included: { filePath: string; language: string | null }[];\n /** Paths referenced by imports that could not be resolved to a file. */\n unresolved: string[];\n}\n\n/**\n * Build the compressed context for an open file.\n * `activeFilePath` may be absolute or project-relative.\n */\nexport function assemble(\n activeFilePath: string,\n cache: GraphCache,\n opts: AssembleOptions = {},\n): AssembleResult {\n const { includeStats = false, maxSkeletons = 50, pruneActiveFile = false } = opts;\n\n const abs = path.resolve(activeFilePath);\n const activeSource = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf8') : '';\n const activeEntry = cache.get(abs);\n\n const included: AssembleResult['included'] = [];\n const unresolved: string[] = [];\n\n // Ring 1: walk the active file's direct imports.\n const seen = new Set<string>();\n if (activeEntry) {\n for (const imp of activeEntry.imports) {\n const entry = cache.get(imp);\n if (!entry) {\n unresolved.push(imp);\n continue;\n }\n if (seen.has(imp)) continue;\n seen.add(imp);\n included.push({ filePath: imp, language: entry.language });\n if (included.length >= maxSkeletons) break;\n }\n }\n\n // If the active file is unsupported (no cache entry), try to resolve its\n // imports on the fly from disk so the payload is still useful.\n if (!activeEntry && activeSource) {\n // Fallback: derive imports from a lightweight regex and resolve from disk.\n const specifiers = extractSpecifiers(activeSource);\n for (const spec of specifiers) {\n const resolved = resolveLocal(abs, spec);\n if (!resolved) {\n unresolved.push(spec);\n continue;\n }\n if (seen.has(resolved)) continue;\n seen.add(resolved);\n const cached = cache.get(resolved);\n included.push({ filePath: resolved, language: cached?.language ?? null });\n if (included.length >= maxSkeletons) break;\n }\n }\n\n const lines: string[] = [];\n lines.push('# Compressed Code Context', '');\n lines.push(`Active file: \\`${rel(abs)}\\``, '');\n\n // Ring 0.\n lines.push('## Ring 0 — Active file (full text)', '');\n const ring0 = pruneActiveFile && activeEntry ? activeEntry.skeleton : activeSource;\n lines.push(`\\`\\`\\`${ext(activeFilePath)}`);\n lines.push(ring0.trim() || '(empty or unreadable file)');\n lines.push('```', '');\n\n // Ring 1.\n lines.push(\n `## Ring 1 — Pruned dependencies (${included.length})`,\n '',\n 'Implementation bodies removed; type signatures, interfaces and exports retained.',\n '',\n );\n if (included.length === 0) {\n lines.push('_No local dependency skeletons available._', '');\n }\n for (const inc of included) {\n const entry = cache.get(inc.filePath);\n const label = rel(inc.filePath);\n lines.push(`### \\`${label}\\``, '');\n if (entry) {\n lines.push(`\\`\\`\\`${ext(inc.filePath)}`);\n lines.push(entry.skeleton.trim());\n lines.push('```', '');\n } else {\n lines.push('_Unindexed file._', '');\n }\n }\n\n if (unresolved.length > 0) {\n lines.push('## Unresolved imports', '');\n for (const u of unresolved) lines.push(`- \\`${u}\\``);\n lines.push('');\n }\n\n if (includeStats) {\n const depTokens = included.reduce(\n (acc, inc) => {\n const e = cache.get(inc.filePath);\n return e ? acc + approximateTokens(e.skeleton) : acc;\n },\n 0,\n );\n lines.push('---', '');\n lines.push(\n `_Token estimate — active: ${approximateTokens(activeSource)} · pruned deps: ${depTokens}._`,\n '',\n );\n }\n\n return {\n markdown: lines.join('\\n'),\n activeFilePath: abs,\n activeSource,\n included,\n unresolved,\n };\n}\n\n/** Fallback import specifier extraction when no AST index exists yet. */\nexport function extractSpecifiers(source: string): string[] {\n const found: string[] = [];\n // import ... from 'x'; / import 'x'; / require('x')\n const re = /(?:from\\s+['\"`]|import\\s+['\"`]|require\\s*\\(\\s*['\"`])([^'\"`]+)['\"`]/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n if (m[1]) found.push(m[1]);\n }\n return [...new Set(found)];\n}\n\n/** Resolve a fallback specifier to an existing file, mirroring sync.resolveImport. */\nfunction resolveLocal(importer: string, specifier: string): string | null {\n if (!/^[.~@]/.test(specifier)) return null;\n if (specifier.startsWith('@/')) specifier = specifier.slice(2);\n else if (specifier.startsWith('~')) specifier = specifier.slice(1);\n const base = path.dirname(path.resolve(importer));\n const p = path.resolve(base, specifier);\n const candidates = [\n p,\n `${p}.ts`,\n `${p}.tsx`,\n `${p}.js`,\n `${p}.jsx`,\n `${p}.py`,\n `${p}.go`,\n `${p}.rs`,\n `${p}.dart`,\n `${p}.swift`,\n `${p}.java`,\n `${p}.kt`,\n `${p}.c`,\n `${p}.cpp`,\n path.join(p, 'index.ts'),\n path.join(p, 'index.js'),\n ];\n for (const c of candidates) {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return path.resolve(c);\n }\n return null;\n}\n\n/** Relative path for display (fall back to basename). */\nfunction rel(p: string): string {\n try {\n const cwd = process.cwd();\n if (p.startsWith(cwd)) return '.' + p.slice(cwd.length);\n } catch {\n /* noop */\n }\n return p;\n}\n\n/** Return a code-block language label for a file path. */\nfunction ext(p: string): string {\n return path.extname(p).replace(/^\\./, '') || 'text';\n}\n\n/** Rough, dependency-free token approximation (words + punctuation runs). */\nexport function approximateTokens(text: string): number {\n if (!text) return 0;\n const tokens = text.match(/[A-Za-z0-9_$]+|[^A-Za-z0-9_\\s$]/g);\n return tokens ? tokens.length : 0;\n}\n\nexport function assembleFromCache(\n activeFilePath: string,\n cache: GraphCache,\n): AssembleResult {\n return assemble(activeFilePath, cache);\n}\n","/**\n * Incremental synchronization layer (Phase 3).\n *\n * - Watches the repository with chokidar (ignoring vendor/build dirs).\n * - On add/change, hashes the file and, if the hash changed, re-prunes it and\n * updates the in-memory graph cache.\n * - Extracts import/require specifiers from each file and normalizes relative\n * and aliased paths to absolute file paths on disk.\n *\n * The graph cache is shared with the Context Assembler, which reads ring-1\n * skeletons out of it.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\n\nimport chokidar, { type FSWatcher, type Matcher } from 'chokidar';\n\nimport { ensureParserInit, prune } from '../parser/pruner.js';\n\nexport type { Matcher };\n\n/** Default paths that will never be indexed or watched. */\nexport const DEFAULT_IGNORED = [\n /(^|[/\\\\])\\.[^/\\\\]+/, // dotfiles / dot-dirs (.git, .cursor, .env, ...)\n /node_modules/,\n /[/\\\\](build|dist|out|coverage|\\.next|\\.turbo|\\.cache)[/\\\\]/,\n];\n\nexport interface CacheEntry {\n /** sha1 of the last-indexed file content. */\n hash: string;\n /** Pruned skeleton for this file. */\n skeleton: string;\n /** The language name used to prune it (or null if unsupported). */\n language: string | null;\n /** Absolute paths of the files this file imports. */\n imports: string[];\n}\n\nexport type GraphCache = Map<string, CacheEntry>;\n\nexport class ContextCache {\n readonly entries: GraphCache = new Map();\n private initPromise: Promise<void> | null = null;\n\n ensureInit(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = ensureParserInit();\n }\n return this.initPromise;\n }\n\n /** Returns the cached skeleton for a file, if present. */\n getSkeleton(filePath: string): CacheEntry | null {\n return this.entries.get(path.resolve(filePath)) ?? null;\n }\n\n get imports() {\n return this.entries;\n }\n}\n\n/** Compute a sha1 of a string. */\nexport function hashOf(text: string): string {\n return createHash('sha1').update(text).digest('hex');\n}\n\n/**\n * Extract import/require specifiers from source text using a robust,\n * language-agnostic regex (AST-based import queries are grammar-fragile and\n * occasionally malformed; regex covers the common import forms across JS/TS,\n * Python, Go, Rust, Dart, Swift, Java, Kotlin, PHP, C/C++).\n * Returns the matched specifier strings (may be relative or absolute).\n */\nexport function extractImports(_filePath: string, source: string): string[] {\n const out: string[] = [];\n\n // import ... from 'x' | import 'x' | require('x')\n const re =\n /(?:from\\s+['\"`]([^'\"`]+)['\"`]|import\\s+['\"`]([^'\"`]+)['\"`]|require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n const spec = m[1] ?? m[2] ?? m[3];\n if (spec) out.push(spec);\n }\n\n // Python / Go / Rust / Dart / Swift / Java / Kotlin / C/C++ single-quote not\n // covered by the JS-style regex is out of scope for the first pass.\n\n return [...new Set(out)].filter(Boolean);\n}\n\n/** Normalize a specifier to an absolute file path when it resolves locally. */\nexport function resolveImport(\n importer: string,\n specifier: string,\n root: string,\n): string | null {\n // Skip bare, non-relative imports (npm packages) and obviously external.\n if (!/^[.~@]/.test(specifier)) {\n // Alias `@/...` and `~` map to the project root.\n if (specifier.startsWith('@/')) {\n return resolveCandidate(path.join(root, specifier.slice(2)));\n }\n if (specifier.startsWith('@')) {\n return null; // scoped package, not local\n }\n if (specifier.startsWith('~')) {\n return resolveCandidate(path.join(root, specifier.slice(1)));\n }\n return null;\n }\n\n const base = path.dirname(path.resolve(importer));\n return resolveCandidate(path.resolve(base, specifier));\n}\n\n/** Try a specifier with common extension/index additions. */\nfunction resolveCandidate(p: string): string | null {\n const candidates = [\n p,\n `${p}.ts`,\n `${p}.tsx`,\n `${p}.js`,\n `${p}.jsx`,\n `${p}.mjs`,\n `${p}.cjs`,\n `${p}.py`,\n `${p}.go`,\n `${p}.rs`,\n `${p}.dart`,\n `${p}.swift`,\n `${p}.java`,\n `${p}.kt`,\n `${p}.c`,\n `${p}.cpp`,\n `${p}.h`,\n `${p}.hpp`,\n `${p}.php`,\n path.join(p, 'index.ts'),\n path.join(p, 'index.js'),\n path.join(p, 'index.tsx'),\n path.join(p, 'index.jsx'),\n path.join(p, 'index.py'),\n ];\n for (const c of candidates) {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return path.resolve(c);\n }\n return null;\n}\n\nexport interface SyncOptions {\n root: string;\n ignored?: Matcher[];\n onIndexed?: (filePath: string, entry: CacheEntry) => void;\n}\n\n/**\n * Watch a project root and keep the graph cache fresh. Returns the cache and\n * a close() handle. `prune` is awaited per change to keep hot-reload latency\n * predictable.\n */\nexport function createWatcher(opts: SyncOptions) {\n const cache = new ContextCache();\n const { root, ignored = DEFAULT_IGNORED, onIndexed } = opts;\n\n // Debounce a burst of events into a single re-prune per file.\n const pending = new Map<string, NodeJS.Timeout>();\n const DEBOUNCE_MS = 100;\n\n async function handle(filePath: string) {\n const abs = path.resolve(filePath);\n let source: string;\n try {\n const st = fs.statSync(abs);\n if (!st.isFile()) return; // sockets/symlinks etc.\n source = fs.readFileSync(abs, 'utf8');\n } catch {\n return; // file vanished between event and read\n }\n const hash = hashOf(source);\n const cached = cache.entries.get(abs);\n if (cached && cached.hash === hash) return; // unchanged\n\n await cache.ensureInit();\n const { code, language } = await prune(abs, source);\n const imports = await extractImports(abs, source);\n const entry: CacheEntry = {\n hash,\n skeleton: code,\n language,\n imports: imports\n .map((spec) => resolveImport(abs, spec, root))\n .filter((p): p is string => p !== null),\n };\n cache.entries.set(abs, entry);\n onIndexed?.(abs, entry);\n }\n\n const watcher: FSWatcher = chokidar.watch(root, {\n // Combine path matchers with a stat check so non-regular files (e.g. unix\n // sockets) are never opened with fs.watch (which raises UVException).\n ignored(_p, stats) {\n if (stats && !stats.isFile() && !stats.isDirectory()) return true;\n return isIgnored(path.resolve(String(_p)), ignored);\n },\n alwaysStat: true,\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 50, pollInterval: 10 },\n });\n\n function debounce(filePath: string) {\n const abs = path.resolve(filePath);\n const existing = pending.get(abs);\n if (existing) clearTimeout(existing);\n // Fire immediately on the first event, then coalesce noise.\n if (!existing) void handle(abs);\n pending.set(\n abs,\n setTimeout(() => pending.delete(abs), DEBOUNCE_MS),\n );\n }\n\n watcher.on('add', debounce);\n watcher.on('change', debounce);\n watcher.on('unlink', (filePath: string) => {\n const abs = path.resolve(filePath);\n cache.entries.delete(abs);\n });\n\n return {\n cache,\n watcher,\n /** Index an existing file right now (bypasses the watcher). */\n index: handle,\n /**\n * Index the whole tree once (cold start). Returns the number of files\n * successfully indexed.\n */\n async indexAll(): Promise<number> {\n const files: string[] = [];\n await walk(root, (f) => files.push(f), ignored);\n let ok = 0;\n for (const f of files) {\n try {\n await handle(f);\n ok++;\n } catch {\n /* skip unparseable files */\n }\n }\n return ok;\n },\n close: () => watcher.close(),\n };\n}\n\n/** Recursively list supported source files, honoring ignore patterns. */\nasync function walk(\n root: string,\n push: (f: string) => void,\n ignored: Matcher[],\n): Promise<void> {\n const entries = await fs.promises.readdir(root, { withFileTypes: true });\n for (const e of entries) {\n const abs = path.join(root, e.name);\n if (isIgnored(abs, ignored)) continue;\n if (e.isDirectory()) {\n await walk(abs, push, ignored);\n } else if (e.isFile()) {\n push(abs);\n }\n // Skip sockets, symlinks to non-files, devices, etc. to avoid chokidar/fs\n // throwing UVException while trying to watch them.\n }\n}\n\nfunction isIgnored(abs: string, ignored: Matcher[]): boolean {\n for (const m of ignored) {\n if (typeof m === 'string' && abs.includes(m)) return true;\n if (m instanceof RegExp && m.test(abs)) return true;\n }\n return false;\n}\n","/**\n * Polyglot AST pruning engine. Parses a source file with its language grammar\n * and replaces matched implementation blocks with a compact skeleton token,\n * preserving type signatures, interfaces, and module exports.\n *\n * Range splicing is done bottom-up (descending start offset) so that earlier\n * replacements never shift the byte offsets of later ones.\n */\n\nimport Parser from 'web-tree-sitter';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { languageForFile, type LanguageSpec } from './registry.js';\nimport { getGrammar } from './wasm.js';\n\n/** A byte-range that will be replaced by `token`. */\ninterface PruneRange {\n start: number;\n end: number;\n token: string;\n}\n\n/**\n * Cache of decoded web-tree-sitter Language objects, keyed by grammar file\n * name. Grammar bytes only change when the on-disk binary changes, so we can\n * decode once per process and reuse it across all parses for that language.\n */\nconst languageCache = new Map<string, Parser.Language>();\n\nlet initPromise: Promise<void> | null = null;\n/** `Parser.init()` only needs to run once; make concurrent calls share it. */\nexport function ensureParserInit(): Promise<void> {\n if (!initPromise) {\n initPromise = Parser.init({\n locateFile: (file: string) => {\n // Point the wasm runtime at the bundled tree-sitter.wasm so it works\n // from tsup's dist build as well as from node_modules. `__filename` is\n // shimmed by tsup for ESM and native in CJS, avoiding the empty\n // `import.meta.url` that crashes the CJS CLI bundle.\n const require = createRequire(__filename);\n try {\n const pkgRoot = path.dirname(require.resolve('web-tree-sitter/package.json'));\n return path.join(pkgRoot, file);\n } catch {\n return file;\n }\n },\n });\n }\n return initPromise;\n}\n\n/** Load (and cache) a decoded Language object for a language spec. */\nexport function loadLanguage(spec: LanguageSpec, force = false): Promise<Parser.Language> {\n if (!force) {\n const cached = languageCache.get(spec.wasm);\n if (cached) return Promise.resolve(cached);\n }\n // Force re-download/re-decode and refresh the cache.\n if (force) languageCache.delete(spec.wasm);\n return (async () => {\n await ensureParserInit();\n const grammar = await getGrammar(spec, force);\n const language = await Parser.Language.load(grammar);\n languageCache.set(spec.wasm, language);\n return language;\n })();\n}\n\n/**\n * Prune the implementation bodies out of `source` (a file at `filePath`).\n * If the language has no registered rules, returns the source unchanged.\n */\nexport async function prune(\n filePath: string,\n source: string,\n opts: { forceDownload?: boolean } = {},\n): Promise<{ code: string; language: string | null; removed: number }> {\n const spec = languageForFile(filePath);\n if (!spec || spec.rules.length === 0) {\n return { code: source, language: null, removed: 0 };\n }\n\n const language = await loadLanguage(spec, opts.forceDownload);\n\n const parser = new Parser();\n parser.setLanguage(language);\n const tree = parser.parse(source);\n\n const ranges: PruneRange[] = [];\n for (const rule of spec.rules) {\n const query = language.query(rule.query);\n const captures = query.captures(tree.rootNode);\n for (const cap of captures) {\n // Skip captures whose source text is empty (there's nothing to shrink).\n if (cap.node.startIndex === cap.node.endIndex) continue;\n // Allow rules to keep certain blocks (e.g. 'use client/server').\n if (rule.replacement.keepIf?.test(cap.node.text)) continue;\n ranges.push({\n start: cap.node.startIndex,\n end: cap.node.endIndex,\n token: rule.replacement.token,\n });\n }\n query.delete();\n }\n tree.delete();\n parser.delete();\n\n const { code, removed } = spliceRanges(source, ranges);\n return { code, language: spec.name, removed };\n}\n\n/**\n * Replace all ranges with their tokens. Ranges are pre-sorted descending by\n * start offset so each splice happens at the tail of the string first,\n * keeping earlier offsets stable.\n */\nexport function spliceRanges(source: string, ranges: PruneRange[]): {\n code: string;\n removed: number;\n} {\n let removed = 0;\n const sorted = [...ranges].sort((a, b) => b.start - a.start);\n let out = source;\n for (const r of sorted) {\n if (r.start < 0 || r.end > out.length || r.end < r.start) continue;\n removed += r.end - r.start;\n out = out.slice(0, r.start) + r.token + out.slice(r.end);\n }\n return { code: out, removed };\n}\n\n","/**\n * WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar\n * from its upstream GitHub release on first use and caches it on disk in a\n * `wasm/` directory at the project root (mirrored to `dist/wasm` by tsup).\n *\n * `Language.load` on Node expects either a Uint8Array of the real parser\n * bytes or a filesystem path; we hand it the raw bytes via `getGrammar`,\n * which returns a `Uint8Array` for the pruner to load directly.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { LanguageSpec } from './registry.js';\n\n// `__dirname` is shimmed automatically by tsup so it works in both ESM and\n// CJS output: in ESM it derives from import.meta.url, in CJS it is native.\n// This avoids calling fileURLToPath(import.meta.url), which is empty in the\n// CJS bundle and would crash the packaged CLI (`dist/cli.cjs`, `dist/mcp.cjs`).\n/**\n * Resolve the `wasm/` cache directory, preferring the packaged copy.\n * Candidates are searched in order: project `wasm/`, `dist/wasm/`.\n */\nfunction resolveWasmDir(): string {\n const candidates = [\n path.resolve(__dirname, '../../wasm'),\n path.resolve(__dirname, '../wasm'),\n path.resolve(process.cwd(), 'wasm'),\n ];\n for (const dir of candidates) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n } catch {\n /* try next */\n }\n }\n const dir = path.resolve(process.cwd(), 'wasm');\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nlet wasmDir: string | null = null;\nfunction cacheDir(): string {\n if (!wasmDir) wasmDir = resolveWasmDir();\n return wasmDir;\n}\n\nexport function cachePath(spec: LanguageSpec): string {\n return path.join(cacheDir(), spec.wasm);\n}\n\n/** True if the head bytes are the wasm magic `\\0asm`. */\nfunction looksLikeWasm(bytes: Uint8Array): boolean {\n return (\n bytes.length >= 4 &&\n bytes[0] === 0 &&\n bytes[1] === 97 &&\n bytes[2] === 115 &&\n bytes[3] === 109\n );\n}\n\n/** In-flight downloads keyed by wasm filename, so concurrent callers share one. */\nconst inflight = new Map<string, Promise<Uint8Array>>();\n\nfunction download(spec: LanguageSpec): Promise<Uint8Array> {\n const pending = inflight.get(spec.wasm);\n if (pending) return pending;\n const job = (async () => {\n const res = await fetch(spec.url, { redirect: 'follow' });\n if (!res.ok) {\n throw new Error(\n `Failed to download grammar \"${spec.wasm}\" from ${spec.url} (HTTP ${res.status})`,\n );\n }\n const bytes = new Uint8Array(await res.arrayBuffer());\n if (!looksLikeWasm(bytes)) {\n throw new Error(\n `Downloaded grammar \"${spec.wasm}\" is not valid WebAssembly (got HTML/redirect).`,\n );\n }\n // Write atomically (tmp file + rename) so a concurrent reader never\n // observes a partially-written grammar.\n const target = cachePath(spec);\n const tmp = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, bytes);\n fs.renameSync(tmp, target);\n inflight.delete(spec.wasm);\n return bytes;\n })().catch((err) => {\n inflight.delete(spec.wasm);\n throw err;\n });\n inflight.set(spec.wasm, job);\n return job;\n}\n\n/**\n * Return the raw grammar bytes for a language, downloading them if needed.\n * `force` bypasses the local disk cache (used by tests / `--warm`).\n */\nexport async function getGrammar(\n spec: LanguageSpec,\n force = false,\n): Promise<Uint8Array> {\n if (!force && fs.existsSync(cachePath(spec))) {\n const cached = fs.readFileSync(cachePath(spec));\n if (looksLikeWasm(cached)) return cached;\n }\n return download(spec);\n}\n\n/**\n * Pre-download every supported grammar (used on cold boot / `prune --warm`).\n * Returns the number of grammars that are ready on disk afterward.\n */\nexport async function warmGrammars(specs: LanguageSpec[] = []): Promise<number> {\n const registryModule = await import('./registry.js');\n const list =\n specs.length > 0 ? specs : (Object.values(registryModule.registry) as LanguageSpec[]);\n const unique = new Map<string, LanguageSpec>();\n for (const spec of list) unique.set(spec.wasm, spec);\n const results = await Promise.allSettled(\n [...unique.values()].map((spec) => getGrammar(spec)),\n );\n return results.filter((r) => r.status === 'fulfilled').length;\n}\n\n"],"mappings":"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","names":["path","import_node_path","ext","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","import_node_path","import_node_fs","import_node_path","path","dir","fs","Parser","require","path","path","fs","chokidar","path","picocolors","Fastify","fs"]}
1
+ {"version":3,"sources":["../src/parser/registry.ts","../src/cli.ts","../src/server/assembler.ts","../src/watcher/sync.ts","../src/parser/analyze.ts","../src/parser/wasm.ts","../src/parser/symbols.ts","../src/config.ts"],"sourcesContent":["/**\n * Language registry mapping file extensions to tree-sitter grammars and\n * pruning strategies. Each spec defines:\n * - the web-tree-sitter language name\n * - the `.wasm` file and the authoritative download URL\n * - one or more S-expression queries (the \"prune query\") that match the\n * implementation blocks to remove, plus the replacement token.\n *\n * The empty-query default of '' matches nothing, so the pruner leaves the\n * file untouched when a language has no registered prune rules yet.\n */\n\nimport path from 'node:path';\n\n/** Source of truth mirror in the PRD language matrix. */\nexport type Replacement = {\n /** Token used to replace a pruned block. */\n token: string;\n /**\n * Optional regex, run against the raw block text. If it matches, the block\n * is kept instead of pruned. Used to preserve directive/header lines\n * ('use client/server') even when they live inside an otherwise-pruned body.\n */\n keepIf?: RegExp;\n};\n\nexport interface LanguageSpec {\n /** Friendly name, used in logs and the report header. */\n name: string;\n /** web-tree-sitter `Language.load` file name. */\n wasm: string;\n /** Where to download the `.wasm` binary if not cached locally. */\n url: string;\n /** Extensions that map to this language: `.ts`, `.tsx`, etc. */\n extensions: string[];\n /**\n * One or more (query, replacement) pairs. Blocks matched by each query are\n * pruned bottom-up. Queries are combined; a block is pruned if it matches\n * any. This keeps small, frequently repeated constructs cheap to configure.\n */\n rules: { query: string; replacement: Replacement }[];\n}\n\n// ---------------------------------------------------------------------------\n// Pruning workhorse: prune every `statement_block` / `block` node.\n// ---------------------------------------------------------------------------\n\nconst BLOCK = { query: '(statement_block) @block', replacement: { token: '/* ... */' } };\nconst SWIFT_BLOCK = { query: '(statements) @block', replacement: { token: '/* ... */' } };\nconst GO_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst RUST_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst PY_BLOCK = { query: '(block) @block', replacement: { token: 'pass' } };\nconst C_BLOCK = { query: '(compound_statement) @block', replacement: { token: '/* ... */' } };\nconst JAVA_BLOCK = {\n query: '(block) @block',\n replacement: { token: '/* ... */' },\n};\nconst PHP_BLOCK = {\n query: '(compound_statement) @block',\n replacement: { token: '/* ... */' },\n};\nconst KOTLIN_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\nconst DART_BLOCK = { query: '(block) @block', replacement: { token: '/* ... */' } };\n\n// Keeps `'use client'`/`'use server'` and top-level directive strings.\nconst DIRECTIVE_KEEP: Replacement = {\n token: '/* ... */',\n keepIf: /^\\s*'use (client|server)'/,\n};\n\nexport const registry: Record<string, LanguageSpec> = {\n typescript: {\n name: 'TypeScript',\n wasm: 'tree-sitter-typescript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-typescript/releases/latest/download/tree-sitter-typescript.wasm',\n extensions: ['.ts', '.cts', '.mts'],\n rules: [BLOCK],\n },\n javascript: {\n name: 'JavaScript',\n wasm: 'tree-sitter-javascript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-javascript/releases/latest/download/tree-sitter-javascript.wasm',\n extensions: ['.js', '.cjs', '.mjs'],\n rules: [BLOCK],\n },\n tsx: {\n name: 'React / Next.js (TSX)',\n wasm: 'tree-sitter-tsx.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-typescript/releases/latest/download/tree-sitter-tsx.wasm',\n extensions: ['.tsx'],\n rules: [{ query: '(statement_block) @block', replacement: DIRECTIVE_KEEP }],\n },\n jsx: {\n name: 'React (JSX)',\n wasm: 'tree-sitter-javascript.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-javascript/releases/latest/download/tree-sitter-javascript.wasm',\n extensions: ['.jsx'],\n rules: [{ query: '(statement_block) @block', replacement: DIRECTIVE_KEEP }],\n },\n python: {\n name: 'Python',\n wasm: 'tree-sitter-python.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-python/releases/latest/download/tree-sitter-python.wasm',\n extensions: ['.py', '.pyi'],\n rules: [PY_BLOCK],\n },\n dart: {\n name: 'Dart / Flutter',\n wasm: 'tree-sitter-dart.wasm',\n url: 'https://github.com/UserNobody14/tree-sitter-dart.wasm/releases/latest/download/tree-sitter-dart.wasm',\n extensions: ['.dart'],\n rules: [DART_BLOCK],\n },\n swift: {\n name: 'Swift / SwiftUI',\n wasm: 'tree-sitter-swift.wasm',\n url: 'https://github.com/alex-pinkus/tree-sitter-swift/releases/latest/download/tree-sitter-swift.wasm',\n extensions: ['.swift'],\n rules: [SWIFT_BLOCK],\n },\n go: {\n name: 'Go',\n wasm: 'tree-sitter-go.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-go/releases/latest/download/tree-sitter-go.wasm',\n extensions: ['.go'],\n rules: [GO_BLOCK],\n },\n rust: {\n name: 'Rust',\n wasm: 'tree-sitter-rust.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-rust/releases/latest/download/tree-sitter-rust.wasm',\n extensions: ['.rs'],\n rules: [RUST_BLOCK],\n },\n java: {\n name: 'Java',\n wasm: 'tree-sitter-java.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-java/releases/latest/download/tree-sitter-java.wasm',\n extensions: ['.java'],\n rules: [JAVA_BLOCK],\n },\n kotlin: {\n name: 'Kotlin',\n wasm: 'tree-sitter-kotlin.wasm',\n url: 'https://github.com/fwcd/tree-sitter-kotlin/releases/latest/download/tree-sitter-kotlin.wasm',\n extensions: ['.kt', '.kts'],\n rules: [KOTLIN_BLOCK],\n },\n c: {\n name: 'C',\n wasm: 'tree-sitter-c.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-c/releases/latest/download/tree-sitter-c.wasm',\n extensions: ['.c', '.h'],\n rules: [C_BLOCK],\n },\n cpp: {\n name: 'C++',\n wasm: 'tree-sitter-cpp.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-cpp/releases/latest/download/tree-sitter-cpp.wasm',\n extensions: ['.cc', '.cpp', '.cxx', '.hpp', '.hh', '.hxx'],\n rules: [C_BLOCK],\n },\n php: {\n name: 'PHP',\n wasm: 'tree-sitter-php.wasm',\n url: 'https://github.com/tree-sitter/tree-sitter-php/releases/latest/download/tree-sitter-php.wasm',\n extensions: ['.php'],\n rules: [PHP_BLOCK],\n },\n} satisfies Record<string, LanguageSpec>;\n\n/** Map of extension -> language spec id, built once. */\nconst extensionIndex = new Map<string, string>();\nfor (const [id, spec] of Object.entries(registry)) {\n for (const ext of spec.extensions) {\n extensionIndex.set(ext, id);\n }\n}\n\nexport type LanguageId = keyof typeof registry;\n\n/** Return the language spec for a file path, or null if unsupported. */\nexport function languageForFile(filePath: string): LanguageSpec | null {\n const langId = extensionIndex.get(path.extname(filePath).toLowerCase());\n if (!langId) return null;\n return registry[langId];\n}\n\n/** All languages that have at least one prune rule. */\nexport const supportedLanguageIds = Object.keys(registry) as LanguageId[];\n\n/** Convenience: list every known extension. */\nexport const allExtensions = [...extensionIndex.keys()];\n","/**\n * HTTP/CLI server. Exposes the context assembler as a small Fastify service:\n *\n * GET /health -> liveness\n * POST /v1/context -> { activeFilePath, maxSkeletons?, includeStats? } => markdown\n *\n * Run as `token-shrink` or `node dist/cli.js`. The server watches `--root`\n * (defaults to cwd) and keeps the import graph + skeletons warm.\n */\n\nimport Fastify from 'fastify';\nimport picocolors from 'picocolors';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { assembleMany } from './server/assembler.js';\nimport { createWatcher, type Matcher } from './watcher/sync.js';\nimport { warmGrammars } from './parser/wasm.js';\n\nexport interface CliOptions {\n port?: number;\n host?: string;\n root?: string;\n ignored?: Matcher[];\n silent?: boolean;\n}\n\nfunction parseArgv(argv = process.argv): Record<string, string> {\n const out: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const cur = argv[i];\n if (cur?.startsWith('--')) {\n const key = cur.slice(2);\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n out[key] = next;\n i++;\n } else {\n out[key] = 'true';\n }\n }\n }\n return out;\n}\n\n/** Start the Fastify server; returns the running instance + watcher handle. */\nexport async function startServer(opts: CliOptions = {}) {\n const args = parseArgv();\n const port = opts.port ?? Number(args.port ?? process.env.PORT ?? 3000);\n const host = opts.host ?? args.host ?? '0.0.0.0';\n const root = path.resolve(opts.root ?? args.root ?? process.cwd());\n const silent = opts.silent ?? args.silent === 'true';\n // Optional server-wide token budget: --max-tokens 4000.\n const maxTokensDefault = args['max-tokens']\n ? Number(args['max-tokens'])\n : undefined;\n\n const log = (msg: string) => {\n if (!silent) console.log(picocolors.dim(msg));\n };\n\n // Warm grammars in the background so the first prune isn't slow.\n void warmGrammars().catch(() => {});\n\n const watcher = createWatcher({ root, ignored: opts.ignored });\n log(`Indexing ${root} in the background…`);\n void watcher.indexAll().then((n) => log(`Indexed ${n} files.`));\n\n const app = Fastify({ logger: !silent });\n\n app.get('/health', async () => ({\n status: 'ok',\n service: 'token-shrink',\n version: '2.0.0',\n root,\n indexed: watcher.cache.entries.size,\n }));\n\n app.post('/v1/context', async (req, reply) => {\n const body = (req.body ?? {}) as {\n activeFilePath?: string;\n activeFiles?: string[];\n maxSkeletons?: number;\n maxTokens?: number;\n includeStats?: boolean;\n };\n const hasMany = Array.isArray(body.activeFiles) && body.activeFiles.length > 0;\n if (hasMany && body.activeFilePath) {\n return reply\n .status(400)\n .send({ error: 'Pass either `activeFilePath` or `activeFiles`, not both.' });\n }\n const paths = hasMany\n ? (body.activeFiles as string[])\n : body.activeFilePath\n ? [body.activeFilePath]\n : [];\n if (paths.length === 0) {\n return reply.status(400).send({ error: '`activeFilePath` or `activeFiles` is required' });\n }\n const maxTokens =\n body.maxTokens !== undefined ? body.maxTokens : maxTokensDefault;\n const result = assembleMany(paths, watcher.cache.entries, {\n maxSkeletons: body.maxSkeletons,\n maxTokens: Number.isFinite(maxTokens as number) ? (maxTokens as number) : undefined,\n includeStats: body.includeStats,\n });\n return {\n markdown: result.markdown,\n activeFilePath: result.activeFilePath,\n activeFilePaths: result.activeFilePaths,\n dependencies: result.included.map((i) => i.filePath),\n unresolved: result.unresolved,\n tokenStats: result.tokenStats,\n };\n });\n\n app.setNotFoundHandler(async (req, reply) => {\n void req;\n return reply.status(404).send({ error: 'Not found' });\n });\n\n await app.listen({ port, host });\n log(`Listening on http://${host}:${port}`);\n\n return { app, watcher };\n}\n\n// Start when invoked directly (`node dist/cli.cjs` / the `token-shrink` bin),\n// not when imported as a library. `realpathSync` resolves the npm bin symlink,\n// so `token-shrink` -> `dist/cli.cjs` is detected as `cli.cjs`.\nconst argv1 = process.argv[1] ? path.basename(process.argv[1]) : '';\nlet argv1Real = '';\ntry {\n argv1Real = process.argv[1]\n ? path.basename(fs.realpathSync(process.argv[1]))\n : '';\n} catch {\n /* path may not exist yet (tsx/dev runners) — fall back to argv basename */\n}\nif (\n argv1 === 'cli.js' || argv1 === 'cli.mjs' ||\n argv1 === 'cli.cjs' || argv1 === 'cli.ts' ||\n argv1Real === 'cli.js' || argv1Real === 'cli.mjs' ||\n argv1Real === 'cli.cjs' || argv1Real === 'cli.ts'\n) {\n startServer().catch((err) => {\n console.error(picocolors.red(`[token-shrink] ${err.message}`));\n process.exitCode = 1;\n });\n}\n","/**\n * Context Assembler (Phase 4). Produces a Markdown context payload from the\n * graph cache:\n *\n * Ring 0 — the active file's raw, full text.\n * Ring 1 — pruned skeletons of the files it directly imports.\n *\n * The payload keeps full type signatures (imports, interfaces, exports) while\n * dropping implementation bodies, delivering the 80–90% reduction target.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { GraphCache } from '../watcher/sync.js';\n\nexport interface AssembleOptions {\n /** Number of PRD-style stats to append (disabled by default). */\n includeStats?: boolean;\n /** Maximum number of ring-1 files to include. */\n maxSkeletons?: number;\n /**\n * Hard token budget for the whole payload (Ring 0 + Ring 1). When set, Ring 1\n * candidates are ranked by relevance and greedily packed until the budget is\n * exhausted; Ring 0 is always kept in full.\n */\n maxTokens?: number;\n /** Whether the active file itself should also be pruned (Ring 0 raw by default). */\n pruneActiveFile?: boolean;\n}\n\n/** Token accounting for an assembled payload. */\nexport interface TokenStats {\n activeTokens: number;\n dependencyTokens: number;\n totalTokens: number;\n /** When `maxTokens` was supplied, the budget that was enforced. */\n budget?: number;\n /** Number of Ring 1 candidates dropped by the token budget. */\n trimmed: number;\n}\n\nexport interface AssembleResult {\n /** Human-readable Markdown payload for an agent. */\n markdown: string;\n /** First active file (back-compat; prefer `activeFilePaths`). */\n activeFilePath: string;\n /** Every resolved Ring-0 path, in request order. */\n activeFilePaths: string[];\n /** Ring-0 full text of the active file(s). */\n activeSource: string;\n /** Ring-1 entries actually included. */\n included: { filePath: string; language: string | null }[];\n /** Paths referenced by imports that could not be resolved to a file. */\n unresolved: string[];\n /** Approximate token accounting for this payload. */\n tokenStats: TokenStats;\n}\n\n/** Markdown headers/fences overhead subtracted from a `maxTokens` budget. */\nconst MARKDOWN_OVERHEAD_TOKENS = 40;\n\n/**\n * Build the compressed context for one or more open files.\n * `activeFiles` may be absolute or project-relative. Every listed file is\n * emitted in full as Ring 0; the combined set of their local imports is\n * emitted as pruned Ring-1 skeletons, minus any file already in Ring 0.\n *\n * When `opts.maxTokens` is set, Ring 1 candidates are ranked by a cheap\n * relevance proxy (fan-in → path depth → declaration order) and greedily\n * packed until the budget is exhausted; Ring 0 is always kept in full.\n */\nexport function assembleMany(\n activeFiles: string[],\n cache: GraphCache,\n opts: AssembleOptions = {},\n): AssembleResult {\n const {\n includeStats = false,\n maxSkeletons = 50,\n maxTokens,\n pruneActiveFile = false,\n } = opts;\n\n const absList = activeFiles.map((p) => path.resolve(p));\n const sources = absList.map((abs) => {\n try {\n return fs.readFileSync(abs, 'utf8');\n } catch {\n return '';\n }\n });\n const activeSet = new Set(absList);\n\n // Ring-0 text that will actually be emitted (pruned only on request).\n const ring0Texts = absList.map((abs, i) => {\n const entry = cache.get(abs);\n return pruneActiveFile && entry ? entry.skeleton : sources[i];\n });\n\n const included: AssembleResult['included'] = [];\n const unresolved: string[] = [];\n const seen = new Set<string>();\n const addUnresolved = (p: string) => {\n if (!unresolved.includes(p)) unresolved.push(p);\n };\n const addIncluded = (p: string, allowUncached: boolean) => {\n if (seen.has(p)) return;\n const entry = cache.get(p);\n if (!entry && !allowUncached) {\n addUnresolved(p);\n return;\n }\n seen.add(p);\n included.push({ filePath: p, language: entry?.language ?? null });\n };\n\n for (let i = 0; i < absList.length; i++) {\n const abs = absList[i];\n const entry = cache.get(abs);\n if (entry) {\n // Indexed active file: walk its resolved imports.\n for (const imp of entry.imports) {\n if (activeSet.has(imp)) continue; // already full Ring 0\n addIncluded(imp, false);\n }\n } else if (sources[i]) {\n // Unindexed active file: resolve imports from disk with the fallback\n // so the payload is still useful.\n for (const spec of extractSpecifiers(sources[i])) {\n const resolved = resolveLocal(abs, spec);\n if (!resolved) {\n addUnresolved(spec);\n continue;\n }\n if (activeSet.has(resolved)) continue;\n addIncluded(resolved, true);\n }\n }\n }\n\n // Keep declaration order by default (stable output); rank by relevance only\n // when a token budget forces us to drop lower-value dependencies.\n const ordered =\n maxTokens === undefined ? included : rankByRelevance(included, cache);\n\n // Greedy packing: respect maxSkeletons always; additionally stay within the\n // token budget when one is given.\n const budget =\n maxTokens === undefined\n ? undefined\n : Math.max(0, maxTokens - MARKDOWN_OVERHEAD_TOKENS);\n const selected: AssembleResult['included'] = [];\n let trimmed = 0;\n let dependencyTokens = 0;\n for (const cand of ordered) {\n if (selected.length >= maxSkeletons) break;\n const entry = cache.get(cand.filePath);\n // Unindexed candidates get a small nominal cost until they are indexed.\n const cost = entry ? approximateTokens(entry.skeleton) : 8;\n if (budget !== undefined && dependencyTokens + cost > budget) {\n trimmed++;\n continue;\n }\n selected.push(cand);\n dependencyTokens += cost;\n }\n const activeTokens = ring0Texts.reduce(\n (acc, t) => acc + approximateTokens(t),\n 0,\n );\n\n const lines: string[] = [];\n lines.push('# Compressed Code Context', '');\n\n if (absList.length === 1) {\n lines.push(`Active file: \\`${rel(absList[0])}\\``, '');\n } else {\n lines.push('Active files:', '');\n for (const p of absList) lines.push(`- \\`${rel(p)}\\``);\n lines.push('');\n }\n\n // Ring 0.\n lines.push(\n absList.length === 1\n ? '## Ring 0 — Active file (full text)'\n : '## Ring 0 — Active files (full text)',\n '',\n );\n for (let i = 0; i < absList.length; i++) {\n if (absList.length > 1) lines.push(`### \\`${rel(absList[i])}\\``, '');\n const body = ring0Texts[i].trim() || '(empty or unreadable file)';\n lines.push(`\\`\\`\\`${ext(absList[i])}`, body, '```', '');\n }\n\n // Ring 1.\n lines.push(\n `## Ring 1 — Pruned dependencies (${selected.length})`,\n '',\n 'Implementation bodies removed; type signatures, interfaces and exports retained.',\n '',\n );\n if (selected.length === 0) {\n lines.push('_No local dependency skeletons available._', '');\n }\n for (const inc of selected) {\n const entry = cache.get(inc.filePath);\n const label = rel(inc.filePath);\n lines.push(`### \\`${label}\\``, '');\n if (entry) {\n lines.push(`\\`\\`\\`${ext(inc.filePath)}`, entry.skeleton.trim(), '```', '');\n } else {\n lines.push('_Unindexed file._', '');\n }\n }\n if (maxTokens !== undefined && trimmed > 0) {\n lines.push(\n `_Note: token budget of ${maxTokens} excluded ${trimmed} lower-priority dependenc${trimmed === 1 ? 'y' : 'ies'}._`,\n '',\n );\n }\n\n if (unresolved.length > 0) {\n lines.push('## Unresolved imports', '');\n for (const u of unresolved) lines.push(`- \\`${u}\\``);\n lines.push('');\n }\n\n if (includeStats) {\n const budgetNote =\n maxTokens !== undefined ? ` · budget ${maxTokens} (${trimmed} deps trimmed)` : '';\n lines.push(\n '---',\n '',\n `_Token estimate — active: ${activeTokens} · pruned deps: ${dependencyTokens}${budgetNote}._`,\n '',\n );\n }\n\n return {\n markdown: lines.join('\\n'),\n activeFilePath: absList[0] ?? '',\n activeFilePaths: absList,\n activeSource: sources.join('\\n'),\n included: selected,\n unresolved,\n tokenStats: {\n activeTokens,\n dependencyTokens,\n totalTokens: activeTokens + dependencyTokens,\n ...(maxTokens !== undefined ? { budget: maxTokens } : {}),\n trimmed,\n },\n };\n}\n\n/**\n * Build the compressed context for a single open file.\n * `activeFilePath` may be absolute or project-relative.\n */\nexport function assemble(\n activeFilePath: string,\n cache: GraphCache,\n opts: AssembleOptions = {},\n): AssembleResult {\n return assembleMany([activeFilePath], cache, opts);\n}\n\n/** Rank Ring-1 candidates by a cheap relevance proxy: fan-in desc, then depth asc. */\nfunction rankByRelevance(\n candidates: AssembleResult['included'],\n cache: GraphCache,\n): AssembleResult['included'] {\n const fanIn = new Map<string, number>();\n for (const entry of cache.values()) {\n for (const imp of entry.imports) fanIn.set(imp, (fanIn.get(imp) ?? 0) + 1);\n }\n return candidates\n .map((cand, idx) => ({ cand, idx }))\n .sort((a, b) => {\n const fa = fanIn.get(a.cand.filePath) ?? 0;\n const fb = fanIn.get(b.cand.filePath) ?? 0;\n if (fa !== fb) return fb - fa;\n const da = pathDepth(a.cand.filePath);\n const db = pathDepth(b.cand.filePath);\n if (da !== db) return da - db;\n return a.idx - b.idx;\n })\n .map((x) => x.cand);\n}\n\n/** Number of path segments (a rough \"nearby module\" proxy). */\nfunction pathDepth(p: string): number {\n return p.split(/[/\\\\]+/).filter(Boolean).length;\n}\n\n/** Fallback import specifier extraction when no AST index exists yet. */\nexport function extractSpecifiers(source: string): string[] {\n const found: string[] = [];\n // import ... from 'x'; / import 'x'; / require('x')\n const re = /(?:from\\s+['\"`]|import\\s+['\"`]|require\\s*\\(\\s*['\"`])([^'\"`]+)['\"`]/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n if (m[1]) found.push(m[1]);\n }\n return [...new Set(found)];\n}\n\n/** Resolve a fallback specifier to an existing file, mirroring sync.resolveImport. */\nfunction resolveLocal(importer: string, specifier: string): string | null {\n if (!/^[.~@]/.test(specifier)) return null;\n if (specifier.startsWith('@/')) specifier = specifier.slice(2);\n else if (specifier.startsWith('~')) specifier = specifier.slice(1);\n const base = path.dirname(path.resolve(importer));\n const p = path.resolve(base, specifier);\n const candidates = [\n p,\n `${p}.ts`,\n `${p}.tsx`,\n `${p}.js`,\n `${p}.jsx`,\n `${p}.py`,\n `${p}.go`,\n `${p}.rs`,\n `${p}.dart`,\n `${p}.swift`,\n `${p}.java`,\n `${p}.kt`,\n `${p}.c`,\n `${p}.cpp`,\n path.join(p, 'index.ts'),\n path.join(p, 'index.js'),\n ];\n for (const c of candidates) {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return path.resolve(c);\n }\n return null;\n}\n\n/** Relative path for display (fall back to basename). */\nfunction rel(p: string): string {\n try {\n const cwd = process.cwd();\n if (p.startsWith(cwd)) return '.' + p.slice(cwd.length);\n } catch {\n /* noop */\n }\n return p;\n}\n\n/** Return a code-block language label for a file path. */\nfunction ext(p: string): string {\n return path.extname(p).replace(/^\\./, '') || 'text';\n}\n\n/** Rough, dependency-free token approximation (words + punctuation runs). */\nexport function approximateTokens(text: string): number {\n if (!text) return 0;\n const tokens = text.match(/[A-Za-z0-9_$]+|[^A-Za-z0-9_\\s$]/g);\n return tokens ? tokens.length : 0;\n}\n\nexport function assembleFromCache(\n activeFilePath: string,\n cache: GraphCache,\n): AssembleResult {\n return assemble(activeFilePath, cache);\n}\n","/**\n * Incremental synchronization layer (Phase 3).\n *\n * - Watches the repository with chokidar (ignoring vendor/build dirs).\n * - On add/change, hashes the file and, if the hash changed, re-prunes it and\n * updates the in-memory graph cache.\n * - Extracts import/require specifiers from each file and normalizes relative\n * and aliased paths to absolute file paths on disk.\n *\n * The graph cache is shared with the Context Assembler, which reads ring-1\n * skeletons out of it.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\n\nimport chokidar, { type FSWatcher, type Matcher } from 'chokidar';\n\nimport { ensureParserInit } from '../parser/pruner.js';\nimport { analyze } from '../parser/analyze.js';\nimport type { SymbolInfo } from '../parser/symbols.js';\nimport { matchesAny, type TokenShrinkConfig } from '../config.js';\n\nexport type { Matcher };\n\n/** Default paths that will never be indexed or watched. */\nexport const DEFAULT_IGNORED = [\n /(^|[/\\\\])\\.[^/\\\\]+/, // dotfiles / dot-dirs (.git, .cursor, .env, ...)\n /node_modules/,\n /[/\\\\](build|dist|out|coverage|\\.next|\\.turbo|\\.cache)[/\\\\]/,\n];\n\nexport interface CacheEntry {\n /** sha1 of the last-indexed file content. */\n hash: string;\n /** Pruned skeleton for this file. */\n skeleton: string;\n /** The language name used to prune it (or null if unsupported). */\n language: string | null;\n /** Absolute paths of the files this file imports. */\n imports: string[];\n /** Named definitions found while indexing (for expand_symbol / search). */\n symbols?: SymbolInfo[];\n}\n\nexport type GraphCache = Map<string, CacheEntry>;\n\nexport class ContextCache {\n readonly entries: GraphCache = new Map();\n private initPromise: Promise<void> | null = null;\n\n ensureInit(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = ensureParserInit();\n }\n return this.initPromise;\n }\n\n /** Returns the cached skeleton for a file, if present. */\n getSkeleton(filePath: string): CacheEntry | null {\n return this.entries.get(path.resolve(filePath)) ?? null;\n }\n\n get imports() {\n return this.entries;\n }\n}\n\n/** Compute a sha1 of a string. */\nexport function hashOf(text: string): string {\n return createHash('sha1').update(text).digest('hex');\n}\n\n/**\n * Extract import/require specifiers from source text using a robust,\n * language-agnostic regex (AST-based import queries are grammar-fragile and\n * occasionally malformed; regex covers the common import forms across JS/TS,\n * Python, Go, Rust, Dart, Swift, Java, Kotlin, PHP, C/C++).\n * Returns the matched specifier strings (may be relative or absolute).\n */\nexport function extractImports(_filePath: string, source: string): string[] {\n const out: string[] = [];\n\n // import ... from 'x' | import 'x' | require('x')\n const re =\n /(?:from\\s+['\"`]([^'\"`]+)['\"`]|import\\s+['\"`]([^'\"`]+)['\"`]|require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n const spec = m[1] ?? m[2] ?? m[3];\n if (spec) out.push(spec);\n }\n\n // Python / Go / Rust / Dart / Swift / Java / Kotlin / C/C++ single-quote not\n // covered by the JS-style regex is out of scope for the first pass.\n\n return [...new Set(out)].filter(Boolean);\n}\n\n/** Normalize a specifier to an absolute file path when it resolves locally. */\nexport function resolveImport(\n importer: string,\n specifier: string,\n root: string,\n): string | null {\n // Skip bare, non-relative imports (npm packages) and obviously external.\n if (!/^[.~@]/.test(specifier)) {\n // Alias `@/...` and `~` map to the project root.\n if (specifier.startsWith('@/')) {\n return resolveCandidate(path.join(root, specifier.slice(2)));\n }\n if (specifier.startsWith('@')) {\n return null; // scoped package, not local\n }\n if (specifier.startsWith('~')) {\n return resolveCandidate(path.join(root, specifier.slice(1)));\n }\n return null;\n }\n\n const base = path.dirname(path.resolve(importer));\n return resolveCandidate(path.resolve(base, specifier));\n}\n\n/** Try a specifier with common extension/index additions. */\nfunction resolveCandidate(p: string): string | null {\n const candidates = [\n p,\n `${p}.ts`,\n `${p}.tsx`,\n `${p}.js`,\n `${p}.jsx`,\n `${p}.mjs`,\n `${p}.cjs`,\n `${p}.py`,\n `${p}.go`,\n `${p}.rs`,\n `${p}.dart`,\n `${p}.swift`,\n `${p}.java`,\n `${p}.kt`,\n `${p}.c`,\n `${p}.cpp`,\n `${p}.h`,\n `${p}.hpp`,\n `${p}.php`,\n path.join(p, 'index.ts'),\n path.join(p, 'index.js'),\n path.join(p, 'index.tsx'),\n path.join(p, 'index.jsx'),\n path.join(p, 'index.py'),\n ];\n for (const c of candidates) {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return path.resolve(c);\n }\n return null;\n}\n\nexport interface SyncOptions {\n root: string;\n ignored?: Matcher[];\n /** Optional `.tokenshrinkrc.json` settings. */\n config?: TokenShrinkConfig;\n onIndexed?: (filePath: string, entry: CacheEntry) => void;\n /** Called when a watched file disappears from disk (cache entry dropped). */\n onRemoved?: (filePath: string) => void;\n}\n\n/**\n * Watch a project root and keep the graph cache fresh. Returns the cache and\n * a close() handle. `prune` is awaited per change to keep hot-reload latency\n * predictable.\n */\nexport function createWatcher(opts: SyncOptions) {\n const cache = new ContextCache();\n const { root, ignored = DEFAULT_IGNORED, config, onIndexed, onRemoved } = opts;\n\n // Config `ignorePatterns` become extra matchers evaluated against the path\n // relative to the repo root (so globs like `**/dist/**` behave predictably).\n const rel = (abs: string) => path.relative(root, abs);\n const effectiveIgnored: Matcher[] = [\n ...ignored,\n ...(config?.ignorePatterns?.length\n ? [(_abs: string) => matchesAny(rel(String(_abs)), config.ignorePatterns)]\n : []),\n ];\n\n // Debounce a burst of events into a single re-prune per file.\n const pending = new Map<string, NodeJS.Timeout>();\n const DEBOUNCE_MS = 100;\n\n async function handle(filePath: string) {\n const abs = path.resolve(filePath);\n let source: string;\n try {\n const st = fs.statSync(abs);\n if (!st.isFile()) return; // sockets/symlinks etc.\n source = fs.readFileSync(abs, 'utf8');\n } catch {\n return; // file vanished between event and read\n }\n const hash = hashOf(source);\n const cached = cache.entries.get(abs);\n if (cached && cached.hash === hash) return; // unchanged\n\n await cache.ensureInit();\n const keepFull = config?.keepUnpruned?.length\n ? matchesAny(path.relative(root, abs), config.keepUnpruned)\n : false;\n const { code, language, symbols } = await analyze(abs, source, {\n skipPrune: keepFull,\n preserveAnnotations: config?.preserveAnnotations,\n });\n const imports = extractImports(abs, source);\n const entry: CacheEntry = {\n hash,\n skeleton: code,\n language,\n imports: imports\n .map((spec) => resolveImport(abs, spec, root))\n .filter((p): p is string => p !== null),\n ...(symbols.length > 0 ? { symbols } : {}),\n };\n cache.entries.set(abs, entry);\n onIndexed?.(abs, entry);\n }\n\n const watcher: FSWatcher = chokidar.watch(root, {\n // Combine path matchers with a stat check so non-regular files (e.g. unix\n // sockets) are never opened with fs.watch (which raises UVException).\n ignored(_p, stats) {\n if (stats && !stats.isFile() && !stats.isDirectory()) return true;\n return isIgnored(path.resolve(String(_p)), effectiveIgnored);\n },\n alwaysStat: true,\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 50, pollInterval: 10 },\n });\n\n function debounce(filePath: string) {\n const abs = path.resolve(filePath);\n const existing = pending.get(abs);\n if (existing) clearTimeout(existing);\n // Fire immediately on the first event, then coalesce noise.\n if (!existing) void handle(abs);\n pending.set(\n abs,\n setTimeout(() => pending.delete(abs), DEBOUNCE_MS),\n );\n }\n\n watcher.on('add', debounce);\n watcher.on('change', debounce);\n watcher.on('unlink', (filePath: string) => {\n const abs = path.resolve(filePath);\n cache.entries.delete(abs);\n onRemoved?.(abs);\n });\n\n return {\n cache,\n watcher,\n /** Index an existing file right now (bypasses the watcher). */\n index: handle,\n /**\n * Index the whole tree once (cold start). Returns the number of files\n * successfully indexed.\n */\n async indexAll(): Promise<number> {\n const files: string[] = [];\n await walk(root, (f) => files.push(f), effectiveIgnored);\n let ok = 0;\n for (const f of files) {\n try {\n await handle(f);\n ok++;\n } catch {\n /* skip unparseable files */\n }\n }\n return ok;\n },\n close: () => watcher.close(),\n };\n}\n\n/** Recursively list supported source files, honoring ignore patterns. */\nasync function walk(\n root: string,\n push: (f: string) => void,\n ignored: Matcher[],\n): Promise<void> {\n const entries = await fs.promises.readdir(root, { withFileTypes: true });\n for (const e of entries) {\n const abs = path.join(root, e.name);\n if (isIgnored(abs, ignored)) continue;\n if (e.isDirectory()) {\n await walk(abs, push, ignored);\n } else if (e.isFile()) {\n push(abs);\n }\n // Skip sockets, symlinks to non-files, devices, etc. to avoid chokidar/fs\n // throwing UVException while trying to watch them.\n }\n}\n\nfunction isIgnored(abs: string, ignored: Matcher[]): boolean {\n for (const m of ignored) {\n if (typeof m === 'function') {\n if (m(abs)) return true;\n continue;\n }\n if (typeof m === 'string' && abs.includes(m)) return true;\n if (m instanceof RegExp && m.test(abs)) return true;\n }\n return false;\n}\n","/**\n * Single-parse analysis pass. Produces the pruned skeleton (Ring-1 text) and\n * the per-file symbol index from ONE tree-sitter parse, so the watcher never\n * parses a file twice for pruning and symbol extraction.\n *\n * The previous `prune()` implementation lived in `parser/pruner.ts`; the\n * parser plumbing (init/language cache) moved here and is re-exported from\n * `pruner.ts` for backwards compatibility.\n */\n\nimport Parser from 'web-tree-sitter';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { languageForFile, type LanguageSpec } from './registry.js';\nimport { getGrammar } from './wasm.js';\nimport { collectSymbols, type SymbolInfo } from './symbols.js';\n\n/** A byte-range that will be replaced by `token`. */\nexport interface PruneRange {\n start: number;\n end: number;\n token: string;\n}\n\n/**\n * Cache of decoded web-tree-sitter Language objects, keyed by grammar file\n * name. Grammar bytes only change when the on-disk binary changes, so we can\n * decode once per process and reuse it across all parses for that language.\n */\nconst languageCache = new Map<string, Parser.Language>();\n\nlet initPromise: Promise<void> | null = null;\n/** `Parser.init()` only needs to run once; make concurrent calls share it. */\nexport function ensureParserInit(): Promise<void> {\n if (!initPromise) {\n initPromise = Parser.init({\n locateFile: (file: string) => {\n // Point the wasm runtime at the bundled tree-sitter.wasm so it works\n // from tsup's dist build as well as from node_modules. `__filename` is\n // shimmed by tsup for ESM and native in CJS, avoiding the empty\n // `import.meta.url` that crashes the CJS CLI bundle.\n const require = createRequire(__filename);\n try {\n const pkgRoot = path.dirname(require.resolve('web-tree-sitter/package.json'));\n return path.join(pkgRoot, file);\n } catch {\n return file;\n }\n },\n });\n }\n return initPromise;\n}\n\n/** Load (and cache) a decoded Language object for a language spec. */\nexport function loadLanguage(\n spec: LanguageSpec,\n force = false,\n): Promise<Parser.Language> {\n if (!force) {\n const cached = languageCache.get(spec.wasm);\n if (cached) return Promise.resolve(cached);\n }\n // Force re-download/re-decode and refresh the cache.\n if (force) languageCache.delete(spec.wasm);\n return (async () => {\n await ensureParserInit();\n const grammar = await getGrammar(spec, force);\n const language = await Parser.Language.load(grammar);\n languageCache.set(spec.wasm, language);\n return language;\n })();\n}\n\n/**\n * Replace all ranges with their tokens. Ranges are pre-sorted descending by\n * start offset so each splice happens at the tail of the string first,\n * keeping earlier offsets stable.\n */\nexport function spliceRanges(source: string, ranges: PruneRange[]): {\n code: string;\n removed: number;\n} {\n let removed = 0;\n const sorted = [...ranges].sort((a, b) => b.start - a.start);\n let out = source;\n for (const r of sorted) {\n if (r.start < 0 || r.end > out.length || r.end < r.start) continue;\n removed += r.end - r.start;\n out = out.slice(0, r.start) + r.token + out.slice(r.end);\n }\n return { code: out, removed };\n}\n\nexport interface AnalyzeOptions {\n forceDownload?: boolean;\n /**\n * Keep the full source instead of producing a pruned skeleton (used by\n * `keepUnpruned` config rules). Symbols are still collected.\n */\n skipPrune?: boolean;\n /**\n * Byte ranges to exempt from pruning (used by `preserveAnnotations` config\n * rules). Blocks fully inside an exempted region are kept unpruned.\n */\n keepBlocksInside?: { start: number; end: number }[];\n /**\n * Annotation markers (e.g. `@keepContext`, `@api`). Any definition whose\n * preceding source window contains `@<marker>` is kept fully unpruned.\n */\n preserveAnnotations?: string[];\n}\n\nexport interface AnalyzeResult {\n /** Pruned skeleton, or the full source when skipped/unsupported. */\n code: string;\n /** Friendly language name, or null when unsupported/unavailable. */\n language: string | null;\n /** Number of bytes removed by pruning. */\n removed: number;\n /** Named definitions found in this file. */\n symbols: SymbolInfo[];\n}\n\n/**\n * Prune a file's implementation bodies and index its symbols from a single\n * parse. When the grammar cannot be loaded (e.g. first offline run) the file\n * is kept usable and unpruned rather than being dropped from the index.\n */\nexport async function analyze(\n filePath: string,\n source: string,\n opts: AnalyzeOptions = {},\n): Promise<AnalyzeResult> {\n const spec = languageForFile(filePath);\n if (!spec || spec.rules.length === 0) {\n return { code: source, language: null, removed: 0, symbols: [] };\n }\n\n let language: Parser.Language;\n try {\n language = await loadLanguage(spec, opts.forceDownload);\n } catch {\n return { code: source, language: null, removed: 0, symbols: [] };\n }\n\n const parser = new Parser();\n parser.setLanguage(language);\n const tree = parser.parse(source);\n try {\n const symbols = collectSymbols(tree.rootNode, source);\n if (opts.skipPrune) {\n return { code: source, language: spec.name, removed: 0, symbols };\n }\n\n // Config keep-rules: an annotated definition (or an explicit keep range)\n // protects every prunable block inside it.\n const keepRanges: { start: number; end: number }[] = [\n ...(opts.keepBlocksInside ?? []),\n ...(opts.preserveAnnotations?.length\n ? annotatedKeepRanges(symbols, source, opts.preserveAnnotations)\n : []),\n ];\n const isProtected = (start: number, end: number) =>\n keepRanges.some((k) => k.start <= start && end <= k.end);\n\n const ranges: PruneRange[] = [];\n for (const rule of spec.rules) {\n const query = language.query(rule.query);\n const captures = query.captures(tree.rootNode);\n for (const cap of captures) {\n // Skip captures whose source text is empty (there's nothing to shrink).\n if (cap.node.startIndex === cap.node.endIndex) continue;\n // Allow rules to keep certain blocks (e.g. 'use client/server').\n if (rule.replacement.keepIf?.test(cap.node.text)) continue;\n // Config keep-rules (preserveAnnotations / keepBlocksInside).\n if (isProtected(cap.node.startIndex, cap.node.endIndex)) continue;\n ranges.push({\n start: cap.node.startIndex,\n end: cap.node.endIndex,\n token: rule.replacement.token,\n });\n }\n query.delete();\n }\n\n const { code, removed } = spliceRanges(source, ranges);\n return { code, language: spec.name, removed, symbols };\n } finally {\n tree.delete();\n parser.delete();\n }\n}\n\n/** Back-compat entry point (same contract as the historical `prune`). */\nexport async function prune(\n filePath: string,\n source: string,\n opts: { forceDownload?: boolean } = {},\n): Promise<{ code: string; language: string | null; removed: number }> {\n const res = await analyze(filePath, source, opts);\n return { code: res.code, language: res.language, removed: res.removed };\n}\n\n/** How far back from a definition to look for an annotation line. */\nconst ANNOTATION_WINDOW = 240;\n\n/**\n * Ranges of definitions whose preceding source window mentions any configured\n * annotation (e.g. a `@api` decorator or `// @keepContext` comment). Grammar\n * agnostic: it uses symbol byte ranges plus a plain-text backwards scan, so an\n * annotated function/class keeps ALL of its nested bodies unpruned.\n */\nfunction annotatedKeepRanges(\n symbols: SymbolInfo[],\n source: string,\n annotations: string[],\n): { start: number; end: number }[] {\n if (annotations.length === 0) return [];\n const markers = annotations.filter(Boolean).map(escapeRegExp);\n if (markers.length === 0) return [];\n const re = new RegExp(`@(${markers.join('|')})\\\\b`, 'i');\n return symbols\n .filter((s) => {\n // Look at the slice of source right before the definition. Cut everything\n // back to the last `}`/`;` so an annotation that belongs to a PREVIOUS\n // definition (still inside the 240-char window) can never leak onto the\n // next one.\n const windowStart = Math.max(0, s.start - ANNOTATION_WINDOW);\n const tail = source.slice(windowStart, s.start);\n const cut = Math.max(tail.lastIndexOf('}\\n'), tail.lastIndexOf(';\\n'));\n const relevant = cut === -1 ? tail : tail.slice(cut + 1);\n return re.test(relevant);\n })\n .map((s) => ({ start: s.start, end: s.end }));\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n","/**\n * WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar\n * from its upstream GitHub release on first use and caches it on disk in a\n * `wasm/` directory at the project root (mirrored to `dist/wasm` by tsup).\n *\n * `Language.load` on Node expects either a Uint8Array of the real parser\n * bytes or a filesystem path; we hand it the raw bytes via `getGrammar`,\n * which returns a `Uint8Array` for the pruner to load directly.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { LanguageSpec } from './registry.js';\n\n// `__dirname` is shimmed automatically by tsup so it works in both ESM and\n// CJS output: in ESM it derives from import.meta.url, in CJS it is native.\n// This avoids calling fileURLToPath(import.meta.url), which is empty in the\n// CJS bundle and would crash the packaged CLI (`dist/cli.cjs`, `dist/mcp.cjs`).\n/**\n * Resolve the `wasm/` cache directory, preferring the packaged copy.\n * Candidates are searched in order: project `wasm/`, `dist/wasm/`.\n */\nfunction resolveWasmDir(): string {\n const candidates = [\n path.resolve(__dirname, '../../wasm'),\n path.resolve(__dirname, '../wasm'),\n path.resolve(process.cwd(), 'wasm'),\n ];\n for (const dir of candidates) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n } catch {\n /* try next */\n }\n }\n const dir = path.resolve(process.cwd(), 'wasm');\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nlet wasmDir: string | null = null;\nfunction cacheDir(): string {\n if (!wasmDir) wasmDir = resolveWasmDir();\n return wasmDir;\n}\n\nexport function cachePath(spec: LanguageSpec): string {\n return path.join(cacheDir(), spec.wasm);\n}\n\n/** True if the head bytes are the wasm magic `\\0asm`. */\nfunction looksLikeWasm(bytes: Uint8Array): boolean {\n return (\n bytes.length >= 4 &&\n bytes[0] === 0 &&\n bytes[1] === 97 &&\n bytes[2] === 115 &&\n bytes[3] === 109\n );\n}\n\n/** In-flight downloads keyed by wasm filename, so concurrent callers share one. */\nconst inflight = new Map<string, Promise<Uint8Array>>();\n\nfunction download(spec: LanguageSpec): Promise<Uint8Array> {\n const pending = inflight.get(spec.wasm);\n if (pending) return pending;\n const job = (async () => {\n const res = await fetch(spec.url, { redirect: 'follow' });\n if (!res.ok) {\n throw new Error(\n `Failed to download grammar \"${spec.wasm}\" from ${spec.url} (HTTP ${res.status})`,\n );\n }\n const bytes = new Uint8Array(await res.arrayBuffer());\n if (!looksLikeWasm(bytes)) {\n throw new Error(\n `Downloaded grammar \"${spec.wasm}\" is not valid WebAssembly (got HTML/redirect).`,\n );\n }\n // Write atomically (tmp file + rename) so a concurrent reader never\n // observes a partially-written grammar.\n const target = cachePath(spec);\n const tmp = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, bytes);\n fs.renameSync(tmp, target);\n inflight.delete(spec.wasm);\n return bytes;\n })().catch((err) => {\n inflight.delete(spec.wasm);\n throw err;\n });\n inflight.set(spec.wasm, job);\n return job;\n}\n\n/**\n * Return the raw grammar bytes for a language, downloading them if needed.\n * `force` bypasses the local disk cache (used by tests / `--warm`).\n */\nexport async function getGrammar(\n spec: LanguageSpec,\n force = false,\n): Promise<Uint8Array> {\n if (!force && fs.existsSync(cachePath(spec))) {\n const cached = fs.readFileSync(cachePath(spec));\n if (looksLikeWasm(cached)) return cached;\n }\n return download(spec);\n}\n\n/**\n * Pre-download every supported grammar (used on cold boot / `prune --warm`).\n * Returns the number of grammars that are ready on disk afterward.\n */\nexport async function warmGrammars(specs: LanguageSpec[] = []): Promise<number> {\n const registryModule = await import('./registry.js');\n const list =\n specs.length > 0 ? specs : (Object.values(registryModule.registry) as LanguageSpec[]);\n const unique = new Map<string, LanguageSpec>();\n for (const spec of list) unique.set(spec.wasm, spec);\n const results = await Promise.allSettled(\n [...unique.values()].map((spec) => getGrammar(spec)),\n );\n return results.filter((r) => r.status === 'fulfilled').length;\n}\n\n","/**\n * Symbol extraction from a parsed tree. One tree-sitter parse yields every\n * named definition (function/class/interface/…) with its byte range, so the\n * MCP server can:\n * - `expand_symbol`: return a specific definition's full, un-pruned body;\n * - `search_symbol_signatures`: index names + signature lines for fast lookup.\n *\n * Node types are matched by name across grammars, and definitions are only\n * kept when the grammar exposes a `name` field (verified for TS/JS/TSX/JSX,\n * Python, Go, Rust, Kotlin, Dart, Swift, Java, PHP). Grammars without a\n * `name` field (e.g. C/C++ `function_definition`) simply contribute nothing.\n */\n\nimport type { SyntaxNode } from 'web-tree-sitter';\n\nexport type SymbolKind =\n | 'function'\n | 'method'\n | 'arrow'\n | 'class'\n | 'interface'\n | 'enum'\n | 'type'\n | 'other';\n\nexport interface SymbolInfo {\n name: string;\n kind: SymbolKind;\n /** 1-based line of the definition start. */\n line: number;\n /** Byte range in the original source (the full definition, body included). */\n start: number;\n end: number;\n /** First line of the definition (trimmed, capped) for search previews. */\n signature?: string;\n}\n\n/** Map of tree-sitter node types to a symbol kind (unique keys only). */\nconst KIND_BY_TYPE: Record<string, SymbolKind> = {\n // TypeScript / JavaScript / TSX / JSX\n function_declaration: 'function',\n generator_function_declaration: 'function',\n function_expression: 'function',\n function_signature_item: 'function',\n method_definition: 'method',\n method_signature: 'method',\n class_declaration: 'class',\n abstract_class_declaration: 'class',\n interface_declaration: 'interface',\n enum_declaration: 'enum',\n type_alias_declaration: 'type',\n // Python\n function_definition: 'function',\n class_definition: 'class',\n // Go\n method_declaration: 'method',\n type_spec: 'type',\n // Rust\n function_item: 'function',\n struct_item: 'class',\n enum_item: 'enum',\n trait_item: 'interface',\n type_item: 'type',\n // Java / Kotlin / PHP / Dart / Swift (best-effort generic names)\n constructor_declaration: 'method',\n module_declaration: 'class',\n protocol_declaration: 'interface',\n};\n\n/** Signature preview cap. */\nconst SIGNATURE_MAX = 200;\n\n/**\n * Walk `root` and collect every named definition with its byte range.\n * `source` is only needed to build signature/line previews.\n */\nexport function collectSymbols(root: SyntaxNode, source: string): SymbolInfo[] {\n const out: SymbolInfo[] = [];\n const walk = (node: SyntaxNode) => {\n const kind = KIND_BY_TYPE[node.type];\n if (kind) {\n const nameNode = node.childForFieldName('name');\n if (nameNode && nameNode.text.trim()) {\n out.push(symbolFrom(nameNode.text.trim(), kind, node.startIndex, node.endIndex, source));\n }\n } else if (node.type === 'variable_declarator') {\n // `const fn = (…) => …` / `const f = function () { … }`\n const value = node.childForFieldName('value');\n const valueType = value?.type;\n if (valueType === 'arrow_function' || valueType === 'function_expression') {\n const nameNode = node.childForFieldName('name');\n if (nameNode && nameNode.text.trim()) {\n out.push(\n symbolFrom(nameNode.text.trim(), 'arrow', node.startIndex, node.endIndex, source),\n );\n }\n }\n }\n // Keep descending so nested methods/inner functions are indexed too.\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (child) walk(child);\n }\n };\n walk(root);\n return out;\n}\n\n/**\n * Resolve `query` to matching symbols. Exact name match wins; falls back to\n * case-insensitive exact, then substring. `kind` narrows the candidates.\n */\nexport function matchSymbols(\n symbols: SymbolInfo[],\n query: string,\n kind?: SymbolKind,\n): SymbolInfo[] {\n const q = query.trim();\n if (!q) return [];\n const pool = kind ? symbols.filter((s) => s.kind === kind) : symbols;\n const byName = pool.filter((s) => s.name === q);\n if (byName.length > 0) return byName;\n const byNameCi = pool.filter((s) => s.name.toLowerCase() === q.toLowerCase());\n if (byNameCi.length > 0) return byNameCi;\n const lower = q.toLowerCase();\n const bySubstring = pool.filter((s) => s.name.toLowerCase().includes(lower));\n return bySubstring.length > 0\n ? bySubstring\n : pool.filter((s) => (s.signature ?? '').toLowerCase().includes(lower));\n}\n\nfunction symbolFrom(\n name: string,\n kind: SymbolKind,\n start: number,\n end: number,\n source: string,\n): SymbolInfo {\n return {\n name,\n kind,\n line: source.slice(0, start).split('\\n').length,\n start,\n end,\n signature: signaturePreview(source, start, end),\n };\n}\n\nfunction signaturePreview(source: string, start: number, end: number): string {\n const nl = source.indexOf('\\n', start);\n const endOfLine = nl === -1 ? end : nl;\n const first = source.slice(start, Math.min(endOfLine, end)).trim();\n return first.length > SIGNATURE_MAX ? `${first.slice(0, SIGNATURE_MAX)}…` : first;\n}\n","/**\n * `.tokenshrinkrc.json` support — developer-level customization.\n *\n * Supported keys (all optional arrays of strings):\n * - ignorePatterns: glob patterns of paths that are never indexed/watched;\n * - keepUnpruned: glob patterns of files to index but never prune;\n * - preserveAnnotations: markers (e.g. `@keepContext`, `@api`) that exempt a\n * definition (and everything nested in it) from pruning.\n *\n * The config file lives at the repository root (the auto-detected root when no\n * `--root` is given). Invalid JSON never crashes the server — it logs a warning\n * and falls back to empty defaults.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport const CONFIG_FILE_NAME = '.tokenshrinkrc.json';\n\nexport interface TokenShrinkConfig {\n /** Glob patterns of paths that should never be indexed or watched. */\n ignorePatterns: string[];\n /** Glob patterns of files to index but never prune (full Ring-1 text). */\n keepUnpruned: string[];\n /** Annotation markers (e.g. `@keepContext`) that exempt a definition from pruning. */\n preserveAnnotations: string[];\n /**\n * When false, the generated agent rule carries only lightweight guidance and\n * the model decides when to call the auxiliary tools on its own. Default\n * (true / unset): rules choreograph the tools automatically each task.\n */\n autoWorkflow?: boolean;\n}\n\nexport const EMPTY_CONFIG: TokenShrinkConfig = {\n ignorePatterns: [],\n keepUnpruned: [],\n preserveAnnotations: [],\n};\n\nexport function configPathFor(root: string): string {\n return path.join(root, CONFIG_FILE_NAME);\n}\n\n/** Parse + validate the config at `root`, tolerating any JSON shape. */\nexport function loadConfig(\n root: string,\n warn?: (msg: string) => void,\n): TokenShrinkConfig {\n const file = configPathFor(root);\n let raw: unknown;\n try {\n if (!fs.existsSync(file)) return { ...EMPTY_CONFIG };\n raw = JSON.parse(fs.readFileSync(file, 'utf8'));\n } catch (err) {\n warn?.(`Invalid ${CONFIG_FILE_NAME} at ${file}: ${(err as Error).message}`);\n return { ...EMPTY_CONFIG };\n }\n return normalizeConfig(raw, warn, file);\n}\n\nfunction normalizeConfig(\n raw: unknown,\n warn?: (msg: string) => void,\n file?: string,\n): TokenShrinkConfig {\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n warn?.(`Invalid ${CONFIG_FILE_NAME}${file ? ` at ${file}` : ''}: expected a JSON object.`);\n return { ...EMPTY_CONFIG };\n }\n const obj = raw as Record<string, unknown>;\n const asStrings = (v: unknown): string[] =>\n Array.isArray(v) ? v.filter((x): x is string => typeof x === 'string') : [];\n return {\n ignorePatterns: asStrings(obj.ignorePatterns),\n keepUnpruned: asStrings(obj.keepUnpruned),\n preserveAnnotations: asStrings(obj.preserveAnnotations),\n ...(typeof obj.autoWorkflow === 'boolean' ? { autoWorkflow: obj.autoWorkflow } : {}),\n };\n}\n\n/** True when the (slash-normalized) `file` matches any `pattern`. */\nexport function matchesAny(file: string, patterns: string[]): boolean {\n const rel = normalizeSlashes(file);\n for (const raw of patterns) {\n if (!raw) continue;\n const pattern = normalizeSlashes(raw).replace(/^\\.\\//, '');\n if (matchesGlob(rel, pattern)) return true;\n }\n return false;\n}\n\n/**\n * Glob matcher with `**`, `*`, `?` and `[...]` support. Patterns that contain\n * no glob metacharacters also match as a path suffix (a bare filename like\n * `global.d.ts` matches any directory containing it).\n */\nexport function matchesGlob(file: string, pattern: string): boolean {\n if (file === pattern) return true;\n if (!/[?*[]/.test(pattern)) {\n // Plain path: exact, or trailing suffix (bare file name / deep dir).\n return file.endsWith(`/${pattern}`);\n }\n const re = globToRegExp(pattern);\n return re.test(file);\n}\n\n/** Compile `**`/`*`/`?`/`[...]` glob into a `/`-normalized regex. */\nexport function globToRegExp(glob: string): RegExp {\n let re = '^';\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i];\n if (c === '*') {\n if (glob[i + 1] === '*') {\n i++;\n // `**/` may match zero or more segments; consume the slash too.\n if (glob[i + 1] === '/') {\n i++;\n re += '(?:.*/)?';\n } else {\n re += '.*';\n }\n } else {\n re += '[^/]*';\n }\n } else if (c === '?') {\n re += '[^/]';\n } else if (c === '[') {\n const close = glob.indexOf(']', i);\n if (close === -1) {\n re += '\\\\[';\n } else {\n const inner = glob.slice(i + 1, close).replace(/\\\\/g, '\\\\\\\\');\n re += `[${inner}]`;\n i = close;\n }\n } else {\n re += c.replace(/[.+^${}()|\\\\]/g, '\\\\$&');\n }\n }\n re += '$';\n return new RegExp(re);\n}\n\nfunction normalizeSlashes(p: string): string {\n return p.split(path.sep).join('/').replace(/^\\.\\//, '');\n}\n"],"mappings":"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","names":["path","import_node_path","ext","import_node_fs","import_node_path","path","fs","path","fs","import_node_fs","import_node_path","import_node_path","import_node_fs","import_node_path","path","dir","fs","walk","Parser","require","path","import_node_fs","import_node_path","rel","path","path","fs","rel","chokidar","path","picocolors","Fastify","fs"]}
package/dist/cli.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import 'chokidar';
2
- export { a as CliOptions, s as startServer } from './cli-EpVqinpB.cjs';
2
+ export { c as CliOptions, s as startServer } from './cli-DzY7l7Rr.cjs';
3
3
  import 'fastify';
4
4
  import 'http';
5
+ import 'web-tree-sitter';
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import 'chokidar';
2
- export { a as CliOptions, s as startServer } from './cli-EpVqinpB.js';
2
+ export { c as CliOptions, s as startServer } from './cli-DzY7l7Rr.js';
3
3
  import 'fastify';
4
4
  import 'http';
5
+ import 'web-tree-sitter';
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-KN4YKUZM.js";
5
- import "./chunk-HRF3BIOV.js";
4
+ } from "./chunk-RI64PBQ5.js";
5
+ import "./chunk-FYCLLG7F.js";
6
6
  import "./chunk-7SQ6HMWM.js";
7
7
  export {
8
8
  startServer