@ajdev0/token-shrink 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +345 -0
- package/dist/chunk-7H6PGILN.js +86 -0
- package/dist/chunk-7H6PGILN.js.map +1 -0
- package/dist/chunk-7SQ6HMWM.js +145 -0
- package/dist/chunk-7SQ6HMWM.js.map +1 -0
- package/dist/chunk-HRF3BIOV.js +518 -0
- package/dist/chunk-HRF3BIOV.js.map +1 -0
- package/dist/chunk-LPJMNP4N.js +179 -0
- package/dist/chunk-LPJMNP4N.js.map +1 -0
- package/dist/cli-EpVqinpB.d.cts +96 -0
- package/dist/cli-EpVqinpB.d.ts +96 -0
- package/dist/cli.cjs +771 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +4 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +10 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +988 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +169 -0
- package/dist/index.d.ts +169 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.cjs +856 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.d.cts +58 -0
- package/dist/mcp.d.ts +58 -0
- package/dist/mcp.js +26 -0
- package/dist/mcp.js.map +1 -0
- package/dist/registry-JLP6X4QB.js +14 -0
- package/dist/registry-JLP6X4QB.js.map +1 -0
- package/dist/tree-sitter-typescript.wasm +0 -0
- package/package.json +59 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parser/registry.ts","../src/index.ts","../src/parser/pruner.ts","../src/parser/wasm.ts","../src/watcher/sync.ts","../src/server/assembler.ts","../src/cli.ts","../src/mcp.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 * token-shrink — public library entry.\n *\n * Re-exports the pruning engine, language registry, incremental watcher/cache,\n * and context assembler for embedding. To run the servers, see `./cli.js`\n * (HTTP) and `./mcp.js` (MCP stdio), which are the packaged CLIs.\n */\n\nexport { prune, spliceRanges } from './parser/pruner.js';\nexport { languageForFile, registry, supportedLanguageIds, allExtensions } from './parser/registry.js';\nexport type { LanguageSpec, Replacement } from './parser/registry.js';\nexport { getGrammar, warmGrammars } from './parser/wasm.js';\n\nexport {\n createWatcher,\n hashOf,\n extractImports,\n resolveImport,\n DEFAULT_IGNORED,\n} from './watcher/sync.js';\nexport type { CacheEntry, GraphCache, SyncOptions } from './watcher/sync.js';\n\nexport { assemble, extractSpecifiers, approximateTokens } from './server/assembler.js';\nexport type { AssembleOptions, AssembleResult } from './server/assembler.js';\n\nexport { startServer } from './cli.js';\nexport type { CliOptions } from './cli.js';\nexport {\n startMcpServer,\n createAutoRule,\n createCursorRule,\n AUTO_RULE_PATH,\n AUTO_RULE_SENTINEL,\n CURSOR_RULE_PATH,\n CLAUDE_RULE_PATH,\n CLAUDE_RULE_SENTINEL,\n RULE_TARGET_PATH,\n} from './mcp.js';\nexport type { McpServerOptions, RuleWriteResult, RuleTarget } from './mcp.js';\n\nexport const version = '2.0.0';\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","/**\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 * 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 * 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 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` / `token-shrink`).\nconst argv1 = process.argv[1] ? path.basename(process.argv[1]) : '';\nif (\n argv1 === 'cli.js' || argv1 === 'cli.mjs' ||\n argv1 === 'cli.cjs' || argv1 === 'cli.ts'\n) {\n startServer().catch((err) => {\n console.error(picocolors.red(`[token-shrink] ${err.message}`));\n process.exitCode = 1;\n });\n}\n","/**\n * MCP stdio server. Exposes a single tool:\n *\n * get_compressed_code_context({ activeFilePath, maxSkeletons?, includeStats? })\n *\n * It maintains its own graph cache by watching the repository root derived\n * from the active file, so Cursor/Claude agents can request pruned context.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\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';\n\n/** Supported auto-rule integration targets. */\nexport type RuleTarget = 'cursor' | 'claude';\n\n/** Agent integration file descriptors written when the auto-rule is on. */\ninterface RuleTargetSpec {\n relPath: string;\n sentinel: string;\n body: string;\n}\n\nexport const RULE_TARGET_PATH = {\n cursor: '.cursor/rules/token-shrink.mdc',\n claude: '.claude/rules/token-shrink.md',\n} as const;\n\nexport const AUTO_RULE_SENTINEL = '# auto-generated by token-shrink';\nexport const CURSOR_RULE_PATH = RULE_TARGET_PATH.cursor;\n/** Back-compat alias for the previous single-target constant. */\nexport const AUTO_RULE_PATH = CURSOR_RULE_PATH;\nexport const CLAUDE_RULE_PATH = RULE_TARGET_PATH.claude;\nexport const CLAUDE_RULE_SENTINEL = '# auto-generated by token-shrink (claude)';\n\nconst ruleTargets: Record<RuleTarget, RuleTargetSpec> = {\n cursor: {\n relPath: CURSOR_RULE_PATH,\n sentinel: AUTO_RULE_SENTINEL,\n body: `---\ndescription: Compress dependency context with token-shrink on every task\nglobs: **/*.{ts,tsx,js,jsx,py,go,rs,dart,swift,java,kt,c,cpp,h,hpp,php}\nalwaysApply: true\n---\nBefore working on a file in this repo, call the \\`get_compressed_code_context\\` MCP tool with\nthat file's path, and use the returned Ring 0 + Ring 1 payload as the context for that file\nand its direct imports.\n\n${AUTO_RULE_SENTINEL}\n`,\n },\n claude: {\n relPath: CLAUDE_RULE_PATH,\n sentinel: CLAUDE_RULE_SENTINEL,\n body: `---\ndescription: Compress dependency context with token-shrink on every task\npaths: [\"**/*.{ts,tsx,js,jsx,py,go,rs,dart,swift,java,kt,c,cpp,h,hpp,php}\"]\n---\nBefore working on a file in this repo, call the \\`get_compressed_code_context\\` MCP tool with\nthat file's path, and use the returned Ring 0 + Ring 1 payload as the context for that file\nand its direct imports.\n\n${CLAUDE_RULE_SENTINEL}\n`,\n },\n};\n\nexport interface McpServerOptions {\n /** Project root. Defaults to cwd. */\n root?: string;\n /** Extra ignore globs for the watcher. */\n ignored?: Matcher[];\n /** Silence log output (stdio must stay clean for the MCP protocol). */\n silent?: boolean;\n /** Whether to auto-write agent integration rules at all. Default true. */\n createRule?: boolean;\n /** Which agent rule target(s) to write. Default both. */\n ruleTarget?: RuleTarget | RuleTarget[];\n}\n\nexport interface RuleWriteResult {\n created: boolean;\n skipped: 'none' | 'exists' | 'user';\n /** Path of the rule file that was considered. */\n filePath: string;\n}\n\n/**\n * Write a rules file for a given agent target. Idempotent:\n * - absent -> create it (tagged with our sentinel);\n * - has our sentinel -> skip (already ours);\n * - present without sentinel -> leave the user's file untouched.\n */\nexport function createAutoRule(root: string, target: RuleTarget): RuleWriteResult {\n const spec = ruleTargets[target];\n const rulePath = path.join(root, spec.relPath);\n try {\n if (fs.existsSync(rulePath)) {\n const existing = fs.readFileSync(rulePath, 'utf8');\n if (existing.includes(spec.sentinel)) {\n return { created: false, skipped: 'exists', filePath: rulePath };\n }\n return { created: false, skipped: 'user', filePath: rulePath };\n }\n fs.mkdirSync(path.dirname(rulePath), { recursive: true });\n fs.writeFileSync(rulePath, spec.body, 'utf8');\n return { created: true, skipped: 'none', filePath: rulePath };\n } catch (err) {\n // Never let a rule-write failure take down the MCP server; surface via result.\n process.stderr.write(\n `[token-shrink] Failed to write rule for \"${target}\": ${(err as Error).message}\\n`,\n );\n return { created: false, skipped: 'none', filePath: rulePath };\n }\n}\n\n/** Back-compat alias for code that imported the old Cursor-only helper. */\nexport function createCursorRule(root: string): RuleWriteResult {\n return createAutoRule(root, 'cursor');\n}\n\n/** Expand `ruleTarget` (single / array / all) into the ordered list to write. */\nfunction resolveTargets(ruleTarget: McpServerOptions['ruleTarget']): RuleTarget[] {\n if (!ruleTarget) return ['cursor', 'claude'];\n const list = Array.isArray(ruleTarget) ? ruleTarget : [ruleTarget];\n if (list.includes('all' as unknown as RuleTarget)) return ['cursor', 'claude'];\n return list;\n}\n\n/**\n * Start the MCP server. Because the MCP protocol runs over stdio, all human\n * logging should go to stderr; stdout is reserved for JSON-RPC.\n */\nexport async function startMcpServer(opts: McpServerOptions = {}): Promise<McpServer> {\n const root = path.resolve(opts.root ?? process.env.ROOT ?? process.cwd());\n const log = (msg: string) => {\n if (!opts.silent) process.stderr.write(`[token-shrink] ${msg}\\n`);\n };\n\n const watcher = createWatcher({ root, ignored: opts.ignored });\n if (!opts.silent) {\n log(`Indexing ${root} in the background…`);\n }\n\n // Auto-create agent integration rules so the tool is used by default.\n if (opts.createRule !== false) {\n for (const target of resolveTargets(opts.ruleTarget)) {\n const res = createAutoRule(root, target);\n if (res.created) {\n log(`Wrote ${target} rule to ${res.filePath}`);\n } else if (res.skipped === 'user') {\n log(`${target} rule exists (user-authored); leaving it untouched.`);\n }\n }\n }\n // Fire-and-forget cold start; zero CPU afterward thanks to the watcher.\n void watcher.indexAll().then((n) => log(`Indexed ${n} files.`));\n\n const server = new McpServer(\n { name: 'token-shrink', version: '2.0.0' },\n { capabilities: { tools: {} } },\n );\n\n server.registerTool(\n 'get_compressed_code_context',\n {\n title: 'Get Compressed Code Context',\n description:\n 'Returns a compressed, framework-aware AST context payload for a file: ' +\n 'the active file’s full source (Ring 0) plus pruned skeletons of its direct ' +\n 'imports (Ring 1). Implementation bodies are removed but type signatures, ' +\n 'interfaces, and module exports are preserved for ~80-90% token reduction.',\n inputSchema: {\n activeFilePath: z.string().describe('Path to the file the agent is working on'),\n maxSkeletons: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Cap on number of dependency skeletons to include'),\n includeStats: z\n .boolean()\n .optional()\n .describe('Append approximate token-count stats'),\n },\n },\n async ({ activeFilePath, maxSkeletons, includeStats }) => {\n const result = assemble(activeFilePath, watcher.cache.entries, {\n maxSkeletons,\n includeStats,\n });\n return {\n content: [\n {\n type: 'text' as const,\n text: result.markdown,\n },\n {\n type: 'text' as const,\n text: `[stats] active=${result.activeFilePath} dependencies=${result.included.length} unresolved=${result.unresolved.length}`,\n },\n ],\n };\n },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n log('MCP server connected.');\n return server;\n}\n\n// Start the server only when run as the MCP binary (`dist/mcp.cjs`), not when\n// imported as a library. Guard against both the source and bundled filenames.\nconst argv1 = process.argv[1] ? path.basename(process.argv[1]) : '';\nif (\n argv1 === 'mcp.js' || argv1 === 'mcp.mjs' ||\n argv1 === 'mcp.cjs' || argv1 === 'mcp.ts'\n) {\n const rootArg = (() => {\n const i = process.argv.indexOf('--root');\n if (i !== -1 && process.argv[i + 1]) return process.argv[i + 1];\n const eq = process.argv.find((a) => a.startsWith('--root='));\n if (eq) return eq.slice('--root='.length);\n return undefined;\n })();\n const createRule = !(\n process.env.TOKEN_SHRINK_CREATE_RULE === '0' ||\n process.env.TOKEN_SHRINK_CREATE_RULE === 'false' ||\n process.env.CONTEXT_SHRINK_CREATE_RULE === '0' ||\n process.env.CONTEXT_SHRINK_CREATE_RULE === 'false' ||\n process.argv.includes('--no-create-rule') ||\n (() => {\n const f = process.argv.find((a) => a.startsWith('--create-rule='));\n return f ? f.slice('--create-rule='.length) === 'false' : false;\n })()\n );\n // --rule-target=cursor|claude|all (repeatable / comma-separated), default all.\n const rawTargets = process.argv\n .filter((a) => a.startsWith('--rule-target='))\n .flatMap((a) => a.slice('--rule-target='.length).split(','));\n const ruleTarget: RuleTarget | RuleTarget[] | undefined =\n rawTargets.length > 0 && !rawTargets.includes('all')\n ? ([...new Set(rawTargets)].filter(\n (v): v is RuleTarget => v === 'cursor' || v === 'claude',\n ) as RuleTarget[])\n : undefined;\n void startMcpServer({ root: rootArg, createRule, ruleTarget }).catch((err) => {\n process.stderr.write(`[token-shrink] MCP server error: ${err.message}\\n`);\n process.exitCode = 1;\n });\n}\n"],"mappings":"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","names":["path","ext","import_node_path","import_node_path","path","dir","fs","Parser","require","path","import_node_fs","import_node_path","path","fs","chokidar","import_node_fs","import_node_path","path","fs","import_node_path","path","picocolors","Fastify","import_node_fs","import_node_path","path","fs","argv1"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { G as GraphCache } from './cli-EpVqinpB.cjs';
|
|
2
|
+
export { C as CacheEntry, a as CliOptions, D as DEFAULT_IGNORED, S as SyncOptions, c as createWatcher, e as extractImports, h as hashOf, r as resolveImport, s as startServer } from './cli-EpVqinpB.cjs';
|
|
3
|
+
export { AUTO_RULE_PATH, AUTO_RULE_SENTINEL, CLAUDE_RULE_PATH, CLAUDE_RULE_SENTINEL, CURSOR_RULE_PATH, McpServerOptions, RULE_TARGET_PATH, RuleTarget, RuleWriteResult, createAutoRule, createCursorRule, startMcpServer } from './mcp.cjs';
|
|
4
|
+
import 'chokidar';
|
|
5
|
+
import 'fastify';
|
|
6
|
+
import 'http';
|
|
7
|
+
import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Language registry mapping file extensions to tree-sitter grammars and
|
|
11
|
+
* pruning strategies. Each spec defines:
|
|
12
|
+
* - the web-tree-sitter language name
|
|
13
|
+
* - the `.wasm` file and the authoritative download URL
|
|
14
|
+
* - one or more S-expression queries (the "prune query") that match the
|
|
15
|
+
* implementation blocks to remove, plus the replacement token.
|
|
16
|
+
*
|
|
17
|
+
* The empty-query default of '' matches nothing, so the pruner leaves the
|
|
18
|
+
* file untouched when a language has no registered prune rules yet.
|
|
19
|
+
*/
|
|
20
|
+
/** Source of truth mirror in the PRD language matrix. */
|
|
21
|
+
type Replacement = {
|
|
22
|
+
/** Token used to replace a pruned block. */
|
|
23
|
+
token: string;
|
|
24
|
+
/**
|
|
25
|
+
* Optional regex, run against the raw block text. If it matches, the block
|
|
26
|
+
* is kept instead of pruned. Used to preserve directive/header lines
|
|
27
|
+
* ('use client/server') even when they live inside an otherwise-pruned body.
|
|
28
|
+
*/
|
|
29
|
+
keepIf?: RegExp;
|
|
30
|
+
};
|
|
31
|
+
interface LanguageSpec {
|
|
32
|
+
/** Friendly name, used in logs and the report header. */
|
|
33
|
+
name: string;
|
|
34
|
+
/** web-tree-sitter `Language.load` file name. */
|
|
35
|
+
wasm: string;
|
|
36
|
+
/** Where to download the `.wasm` binary if not cached locally. */
|
|
37
|
+
url: string;
|
|
38
|
+
/** Extensions that map to this language: `.ts`, `.tsx`, etc. */
|
|
39
|
+
extensions: string[];
|
|
40
|
+
/**
|
|
41
|
+
* One or more (query, replacement) pairs. Blocks matched by each query are
|
|
42
|
+
* pruned bottom-up. Queries are combined; a block is pruned if it matches
|
|
43
|
+
* any. This keeps small, frequently repeated constructs cheap to configure.
|
|
44
|
+
*/
|
|
45
|
+
rules: {
|
|
46
|
+
query: string;
|
|
47
|
+
replacement: Replacement;
|
|
48
|
+
}[];
|
|
49
|
+
}
|
|
50
|
+
declare const registry: Record<string, LanguageSpec>;
|
|
51
|
+
type LanguageId = keyof typeof registry;
|
|
52
|
+
/** Return the language spec for a file path, or null if unsupported. */
|
|
53
|
+
declare function languageForFile(filePath: string): LanguageSpec | null;
|
|
54
|
+
/** All languages that have at least one prune rule. */
|
|
55
|
+
declare const supportedLanguageIds: LanguageId[];
|
|
56
|
+
/** Convenience: list every known extension. */
|
|
57
|
+
declare const allExtensions: string[];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Polyglot AST pruning engine. Parses a source file with its language grammar
|
|
61
|
+
* and replaces matched implementation blocks with a compact skeleton token,
|
|
62
|
+
* preserving type signatures, interfaces, and module exports.
|
|
63
|
+
*
|
|
64
|
+
* Range splicing is done bottom-up (descending start offset) so that earlier
|
|
65
|
+
* replacements never shift the byte offsets of later ones.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/** A byte-range that will be replaced by `token`. */
|
|
69
|
+
interface PruneRange {
|
|
70
|
+
start: number;
|
|
71
|
+
end: number;
|
|
72
|
+
token: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Prune the implementation bodies out of `source` (a file at `filePath`).
|
|
76
|
+
* If the language has no registered rules, returns the source unchanged.
|
|
77
|
+
*/
|
|
78
|
+
declare function prune(filePath: string, source: string, opts?: {
|
|
79
|
+
forceDownload?: boolean;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
code: string;
|
|
82
|
+
language: string | null;
|
|
83
|
+
removed: number;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Replace all ranges with their tokens. Ranges are pre-sorted descending by
|
|
87
|
+
* start offset so each splice happens at the tail of the string first,
|
|
88
|
+
* keeping earlier offsets stable.
|
|
89
|
+
*/
|
|
90
|
+
declare function spliceRanges(source: string, ranges: PruneRange[]): {
|
|
91
|
+
code: string;
|
|
92
|
+
removed: number;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar
|
|
97
|
+
* from its upstream GitHub release on first use and caches it on disk in a
|
|
98
|
+
* `wasm/` directory at the project root (mirrored to `dist/wasm` by tsup).
|
|
99
|
+
*
|
|
100
|
+
* `Language.load` on Node expects either a Uint8Array of the real parser
|
|
101
|
+
* bytes or a filesystem path; we hand it the raw bytes via `getGrammar`,
|
|
102
|
+
* which returns a `Uint8Array` for the pruner to load directly.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Return the raw grammar bytes for a language, downloading them if needed.
|
|
107
|
+
* `force` bypasses the local disk cache (used by tests / `--warm`).
|
|
108
|
+
*/
|
|
109
|
+
declare function getGrammar(spec: LanguageSpec, force?: boolean): Promise<Uint8Array>;
|
|
110
|
+
/**
|
|
111
|
+
* Pre-download every supported grammar (used on cold boot / `prune --warm`).
|
|
112
|
+
* Returns the number of grammars that are ready on disk afterward.
|
|
113
|
+
*/
|
|
114
|
+
declare function warmGrammars(specs?: LanguageSpec[]): Promise<number>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Context Assembler (Phase 4). Produces a Markdown context payload from the
|
|
118
|
+
* graph cache:
|
|
119
|
+
*
|
|
120
|
+
* Ring 0 — the active file's raw, full text.
|
|
121
|
+
* Ring 1 — pruned skeletons of the files it directly imports.
|
|
122
|
+
*
|
|
123
|
+
* The payload keeps full type signatures (imports, interfaces, exports) while
|
|
124
|
+
* dropping implementation bodies, delivering the 80–90% reduction target.
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
interface AssembleOptions {
|
|
128
|
+
/** Number of PRD-style stats to append (disabled by default). */
|
|
129
|
+
includeStats?: boolean;
|
|
130
|
+
/** Maximum number of ring-1 files to include. */
|
|
131
|
+
maxSkeletons?: number;
|
|
132
|
+
/** Whether the active file itself should also be pruned (Ring 0 raw by default). */
|
|
133
|
+
pruneActiveFile?: boolean;
|
|
134
|
+
}
|
|
135
|
+
interface AssembleResult {
|
|
136
|
+
/** Human-readable Markdown payload for an agent. */
|
|
137
|
+
markdown: string;
|
|
138
|
+
activeFilePath: string;
|
|
139
|
+
/** Ring-0 full text of the active file. */
|
|
140
|
+
activeSource: string;
|
|
141
|
+
/** Ring-1 entries actually included. */
|
|
142
|
+
included: {
|
|
143
|
+
filePath: string;
|
|
144
|
+
language: string | null;
|
|
145
|
+
}[];
|
|
146
|
+
/** Paths referenced by imports that could not be resolved to a file. */
|
|
147
|
+
unresolved: string[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build the compressed context for an open file.
|
|
151
|
+
* `activeFilePath` may be absolute or project-relative.
|
|
152
|
+
*/
|
|
153
|
+
declare function assemble(activeFilePath: string, cache: GraphCache, opts?: AssembleOptions): AssembleResult;
|
|
154
|
+
/** Fallback import specifier extraction when no AST index exists yet. */
|
|
155
|
+
declare function extractSpecifiers(source: string): string[];
|
|
156
|
+
/** Rough, dependency-free token approximation (words + punctuation runs). */
|
|
157
|
+
declare function approximateTokens(text: string): number;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* token-shrink — public library entry.
|
|
161
|
+
*
|
|
162
|
+
* Re-exports the pruning engine, language registry, incremental watcher/cache,
|
|
163
|
+
* and context assembler for embedding. To run the servers, see `./cli.js`
|
|
164
|
+
* (HTTP) and `./mcp.js` (MCP stdio), which are the packaged CLIs.
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
declare const version = "2.0.0";
|
|
168
|
+
|
|
169
|
+
export { type AssembleOptions, type AssembleResult, GraphCache, type LanguageSpec, type Replacement, allExtensions, approximateTokens, assemble, extractSpecifiers, getGrammar, languageForFile, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { G as GraphCache } from './cli-EpVqinpB.js';
|
|
2
|
+
export { C as CacheEntry, a as CliOptions, D as DEFAULT_IGNORED, S as SyncOptions, c as createWatcher, e as extractImports, h as hashOf, r as resolveImport, s as startServer } from './cli-EpVqinpB.js';
|
|
3
|
+
export { AUTO_RULE_PATH, AUTO_RULE_SENTINEL, CLAUDE_RULE_PATH, CLAUDE_RULE_SENTINEL, CURSOR_RULE_PATH, McpServerOptions, RULE_TARGET_PATH, RuleTarget, RuleWriteResult, createAutoRule, createCursorRule, startMcpServer } from './mcp.js';
|
|
4
|
+
import 'chokidar';
|
|
5
|
+
import 'fastify';
|
|
6
|
+
import 'http';
|
|
7
|
+
import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Language registry mapping file extensions to tree-sitter grammars and
|
|
11
|
+
* pruning strategies. Each spec defines:
|
|
12
|
+
* - the web-tree-sitter language name
|
|
13
|
+
* - the `.wasm` file and the authoritative download URL
|
|
14
|
+
* - one or more S-expression queries (the "prune query") that match the
|
|
15
|
+
* implementation blocks to remove, plus the replacement token.
|
|
16
|
+
*
|
|
17
|
+
* The empty-query default of '' matches nothing, so the pruner leaves the
|
|
18
|
+
* file untouched when a language has no registered prune rules yet.
|
|
19
|
+
*/
|
|
20
|
+
/** Source of truth mirror in the PRD language matrix. */
|
|
21
|
+
type Replacement = {
|
|
22
|
+
/** Token used to replace a pruned block. */
|
|
23
|
+
token: string;
|
|
24
|
+
/**
|
|
25
|
+
* Optional regex, run against the raw block text. If it matches, the block
|
|
26
|
+
* is kept instead of pruned. Used to preserve directive/header lines
|
|
27
|
+
* ('use client/server') even when they live inside an otherwise-pruned body.
|
|
28
|
+
*/
|
|
29
|
+
keepIf?: RegExp;
|
|
30
|
+
};
|
|
31
|
+
interface LanguageSpec {
|
|
32
|
+
/** Friendly name, used in logs and the report header. */
|
|
33
|
+
name: string;
|
|
34
|
+
/** web-tree-sitter `Language.load` file name. */
|
|
35
|
+
wasm: string;
|
|
36
|
+
/** Where to download the `.wasm` binary if not cached locally. */
|
|
37
|
+
url: string;
|
|
38
|
+
/** Extensions that map to this language: `.ts`, `.tsx`, etc. */
|
|
39
|
+
extensions: string[];
|
|
40
|
+
/**
|
|
41
|
+
* One or more (query, replacement) pairs. Blocks matched by each query are
|
|
42
|
+
* pruned bottom-up. Queries are combined; a block is pruned if it matches
|
|
43
|
+
* any. This keeps small, frequently repeated constructs cheap to configure.
|
|
44
|
+
*/
|
|
45
|
+
rules: {
|
|
46
|
+
query: string;
|
|
47
|
+
replacement: Replacement;
|
|
48
|
+
}[];
|
|
49
|
+
}
|
|
50
|
+
declare const registry: Record<string, LanguageSpec>;
|
|
51
|
+
type LanguageId = keyof typeof registry;
|
|
52
|
+
/** Return the language spec for a file path, or null if unsupported. */
|
|
53
|
+
declare function languageForFile(filePath: string): LanguageSpec | null;
|
|
54
|
+
/** All languages that have at least one prune rule. */
|
|
55
|
+
declare const supportedLanguageIds: LanguageId[];
|
|
56
|
+
/** Convenience: list every known extension. */
|
|
57
|
+
declare const allExtensions: string[];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Polyglot AST pruning engine. Parses a source file with its language grammar
|
|
61
|
+
* and replaces matched implementation blocks with a compact skeleton token,
|
|
62
|
+
* preserving type signatures, interfaces, and module exports.
|
|
63
|
+
*
|
|
64
|
+
* Range splicing is done bottom-up (descending start offset) so that earlier
|
|
65
|
+
* replacements never shift the byte offsets of later ones.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/** A byte-range that will be replaced by `token`. */
|
|
69
|
+
interface PruneRange {
|
|
70
|
+
start: number;
|
|
71
|
+
end: number;
|
|
72
|
+
token: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Prune the implementation bodies out of `source` (a file at `filePath`).
|
|
76
|
+
* If the language has no registered rules, returns the source unchanged.
|
|
77
|
+
*/
|
|
78
|
+
declare function prune(filePath: string, source: string, opts?: {
|
|
79
|
+
forceDownload?: boolean;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
code: string;
|
|
82
|
+
language: string | null;
|
|
83
|
+
removed: number;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Replace all ranges with their tokens. Ranges are pre-sorted descending by
|
|
87
|
+
* start offset so each splice happens at the tail of the string first,
|
|
88
|
+
* keeping earlier offsets stable.
|
|
89
|
+
*/
|
|
90
|
+
declare function spliceRanges(source: string, ranges: PruneRange[]): {
|
|
91
|
+
code: string;
|
|
92
|
+
removed: number;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar
|
|
97
|
+
* from its upstream GitHub release on first use and caches it on disk in a
|
|
98
|
+
* `wasm/` directory at the project root (mirrored to `dist/wasm` by tsup).
|
|
99
|
+
*
|
|
100
|
+
* `Language.load` on Node expects either a Uint8Array of the real parser
|
|
101
|
+
* bytes or a filesystem path; we hand it the raw bytes via `getGrammar`,
|
|
102
|
+
* which returns a `Uint8Array` for the pruner to load directly.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Return the raw grammar bytes for a language, downloading them if needed.
|
|
107
|
+
* `force` bypasses the local disk cache (used by tests / `--warm`).
|
|
108
|
+
*/
|
|
109
|
+
declare function getGrammar(spec: LanguageSpec, force?: boolean): Promise<Uint8Array>;
|
|
110
|
+
/**
|
|
111
|
+
* Pre-download every supported grammar (used on cold boot / `prune --warm`).
|
|
112
|
+
* Returns the number of grammars that are ready on disk afterward.
|
|
113
|
+
*/
|
|
114
|
+
declare function warmGrammars(specs?: LanguageSpec[]): Promise<number>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Context Assembler (Phase 4). Produces a Markdown context payload from the
|
|
118
|
+
* graph cache:
|
|
119
|
+
*
|
|
120
|
+
* Ring 0 — the active file's raw, full text.
|
|
121
|
+
* Ring 1 — pruned skeletons of the files it directly imports.
|
|
122
|
+
*
|
|
123
|
+
* The payload keeps full type signatures (imports, interfaces, exports) while
|
|
124
|
+
* dropping implementation bodies, delivering the 80–90% reduction target.
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
interface AssembleOptions {
|
|
128
|
+
/** Number of PRD-style stats to append (disabled by default). */
|
|
129
|
+
includeStats?: boolean;
|
|
130
|
+
/** Maximum number of ring-1 files to include. */
|
|
131
|
+
maxSkeletons?: number;
|
|
132
|
+
/** Whether the active file itself should also be pruned (Ring 0 raw by default). */
|
|
133
|
+
pruneActiveFile?: boolean;
|
|
134
|
+
}
|
|
135
|
+
interface AssembleResult {
|
|
136
|
+
/** Human-readable Markdown payload for an agent. */
|
|
137
|
+
markdown: string;
|
|
138
|
+
activeFilePath: string;
|
|
139
|
+
/** Ring-0 full text of the active file. */
|
|
140
|
+
activeSource: string;
|
|
141
|
+
/** Ring-1 entries actually included. */
|
|
142
|
+
included: {
|
|
143
|
+
filePath: string;
|
|
144
|
+
language: string | null;
|
|
145
|
+
}[];
|
|
146
|
+
/** Paths referenced by imports that could not be resolved to a file. */
|
|
147
|
+
unresolved: string[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build the compressed context for an open file.
|
|
151
|
+
* `activeFilePath` may be absolute or project-relative.
|
|
152
|
+
*/
|
|
153
|
+
declare function assemble(activeFilePath: string, cache: GraphCache, opts?: AssembleOptions): AssembleResult;
|
|
154
|
+
/** Fallback import specifier extraction when no AST index exists yet. */
|
|
155
|
+
declare function extractSpecifiers(source: string): string[];
|
|
156
|
+
/** Rough, dependency-free token approximation (words + punctuation runs). */
|
|
157
|
+
declare function approximateTokens(text: string): number;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* token-shrink — public library entry.
|
|
161
|
+
*
|
|
162
|
+
* Re-exports the pruning engine, language registry, incremental watcher/cache,
|
|
163
|
+
* and context assembler for embedding. To run the servers, see `./cli.js`
|
|
164
|
+
* (HTTP) and `./mcp.js` (MCP stdio), which are the packaged CLIs.
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
declare const version = "2.0.0";
|
|
168
|
+
|
|
169
|
+
export { type AssembleOptions, type AssembleResult, GraphCache, type LanguageSpec, type Replacement, allExtensions, approximateTokens, assemble, extractSpecifiers, getGrammar, languageForFile, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
startServer
|
|
4
|
+
} from "./chunk-7H6PGILN.js";
|
|
5
|
+
import {
|
|
6
|
+
AUTO_RULE_PATH,
|
|
7
|
+
AUTO_RULE_SENTINEL,
|
|
8
|
+
CLAUDE_RULE_PATH,
|
|
9
|
+
CLAUDE_RULE_SENTINEL,
|
|
10
|
+
CURSOR_RULE_PATH,
|
|
11
|
+
RULE_TARGET_PATH,
|
|
12
|
+
createAutoRule,
|
|
13
|
+
createCursorRule,
|
|
14
|
+
startMcpServer
|
|
15
|
+
} from "./chunk-LPJMNP4N.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_IGNORED,
|
|
18
|
+
approximateTokens,
|
|
19
|
+
assemble,
|
|
20
|
+
createWatcher,
|
|
21
|
+
extractImports,
|
|
22
|
+
extractSpecifiers,
|
|
23
|
+
getGrammar,
|
|
24
|
+
hashOf,
|
|
25
|
+
prune,
|
|
26
|
+
resolveImport,
|
|
27
|
+
spliceRanges,
|
|
28
|
+
warmGrammars
|
|
29
|
+
} from "./chunk-HRF3BIOV.js";
|
|
30
|
+
import {
|
|
31
|
+
allExtensions,
|
|
32
|
+
languageForFile,
|
|
33
|
+
registry,
|
|
34
|
+
supportedLanguageIds
|
|
35
|
+
} from "./chunk-7SQ6HMWM.js";
|
|
36
|
+
|
|
37
|
+
// src/index.ts
|
|
38
|
+
var version = "2.0.0";
|
|
39
|
+
export {
|
|
40
|
+
AUTO_RULE_PATH,
|
|
41
|
+
AUTO_RULE_SENTINEL,
|
|
42
|
+
CLAUDE_RULE_PATH,
|
|
43
|
+
CLAUDE_RULE_SENTINEL,
|
|
44
|
+
CURSOR_RULE_PATH,
|
|
45
|
+
DEFAULT_IGNORED,
|
|
46
|
+
RULE_TARGET_PATH,
|
|
47
|
+
allExtensions,
|
|
48
|
+
approximateTokens,
|
|
49
|
+
assemble,
|
|
50
|
+
createAutoRule,
|
|
51
|
+
createCursorRule,
|
|
52
|
+
createWatcher,
|
|
53
|
+
extractImports,
|
|
54
|
+
extractSpecifiers,
|
|
55
|
+
getGrammar,
|
|
56
|
+
hashOf,
|
|
57
|
+
languageForFile,
|
|
58
|
+
prune,
|
|
59
|
+
registry,
|
|
60
|
+
resolveImport,
|
|
61
|
+
spliceRanges,
|
|
62
|
+
startMcpServer,
|
|
63
|
+
startServer,
|
|
64
|
+
supportedLanguageIds,
|
|
65
|
+
version,
|
|
66
|
+
warmGrammars
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * token-shrink — public library entry.\n *\n * Re-exports the pruning engine, language registry, incremental watcher/cache,\n * and context assembler for embedding. To run the servers, see `./cli.js`\n * (HTTP) and `./mcp.js` (MCP stdio), which are the packaged CLIs.\n */\n\nexport { prune, spliceRanges } from './parser/pruner.js';\nexport { languageForFile, registry, supportedLanguageIds, allExtensions } from './parser/registry.js';\nexport type { LanguageSpec, Replacement } from './parser/registry.js';\nexport { getGrammar, warmGrammars } from './parser/wasm.js';\n\nexport {\n createWatcher,\n hashOf,\n extractImports,\n resolveImport,\n DEFAULT_IGNORED,\n} from './watcher/sync.js';\nexport type { CacheEntry, GraphCache, SyncOptions } from './watcher/sync.js';\n\nexport { assemble, extractSpecifiers, approximateTokens } from './server/assembler.js';\nexport type { AssembleOptions, AssembleResult } from './server/assembler.js';\n\nexport { startServer } from './cli.js';\nexport type { CliOptions } from './cli.js';\nexport {\n startMcpServer,\n createAutoRule,\n createCursorRule,\n AUTO_RULE_PATH,\n AUTO_RULE_SENTINEL,\n CURSOR_RULE_PATH,\n CLAUDE_RULE_PATH,\n CLAUDE_RULE_SENTINEL,\n RULE_TARGET_PATH,\n} from './mcp.js';\nexport type { McpServerOptions, RuleWriteResult, RuleTarget } from './mcp.js';\n\nexport const version = '2.0.0';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCO,IAAM,UAAU;","names":[]}
|