@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/README.md +52 -14
- package/dist/chunk-FYCLLG7F.js +847 -0
- package/dist/chunk-FYCLLG7F.js.map +1 -0
- package/dist/{chunk-KN4YKUZM.js → chunk-RI64PBQ5.js} +17 -7
- package/dist/chunk-RI64PBQ5.js.map +1 -0
- package/dist/chunk-RLHEIKPR.js +894 -0
- package/dist/chunk-RLHEIKPR.js.map +1 -0
- package/dist/cli-DzY7l7Rr.d.cts +182 -0
- package/dist/cli-DzY7l7Rr.d.ts +182 -0
- package/dist/cli.cjs +391 -119
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +2 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +1189 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -20
- package/dist/index.d.ts +160 -20
- package/dist/index.js +37 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.cjs +1126 -136
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts +21 -6
- package/dist/mcp.d.ts +21 -6
- package/dist/mcp.js +6 -2
- package/hooks/claude/README.md +29 -0
- package/hooks/claude/git-impact.mjs +47 -0
- package/hooks/claude/settings.example.json +24 -0
- package/package.json +2 -1
- package/dist/chunk-HBYIAFR4.js +0 -204
- package/dist/chunk-HBYIAFR4.js.map +0 -1
- package/dist/chunk-HRF3BIOV.js +0 -518
- package/dist/chunk-HRF3BIOV.js.map +0 -1
- package/dist/chunk-KN4YKUZM.js.map +0 -1
- package/dist/cli-EpVqinpB.d.cts +0 -96
- package/dist/cli-EpVqinpB.d.ts +0 -96
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp.ts","../src/detect.ts","../src/search/index.ts","../src/git.ts"],"sourcesContent":["/**\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/Cline agents can request pruned context.\n *\n * Root resolution: `--root` (or `ROOT`) pins the project; without one the\n * server auto-detects it from project markers (`.git`, manifests) — first\n * around the process cwd, and lazily from `activeFilePath` once a tool call\n * arrives.\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 { assembleMany } from './server/assembler.js';\nimport { createWatcher, type Matcher } from './watcher/sync.js';\nimport { detectProjectRoot } from './detect.js';\nimport { languageForFile } from './parser/registry.js';\nimport { analyze } from './parser/analyze.js';\nimport { matchSymbols, type SymbolKind } from './parser/symbols.js';\nimport { SymbolSearch } from './search/index.js';\nimport { gitChangedFiles, type GitChangedOptions, type GitDiffScope } from './git.js';\nimport {\n loadConfig,\n configPathFor,\n EMPTY_CONFIG,\n type TokenShrinkConfig,\n} from './config.js';\n\n/** Watcher handle shape returned by `createWatcher`. */\ntype WatcherHandle = ReturnType<typeof createWatcher>;\n\n/** Supported auto-rule integration targets. */\nexport type RuleTarget = 'cursor' | 'claude' | 'cline';\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 cline: '.clinerules/token-shrink.md',\n} as const;\n\n/** Bump when the generated rule bodies gain new tool guidance. */\nexport const RULE_VERSION = 3;\n/** Marker line inside generated rules; its presence means \"current version\". */\nexport const RULE_VERSION_MARKER = `# token-shrink rule v${RULE_VERSION}`;\n\n/**\n * Auto-workflow guidance (default). Instructs the agent to run the right tool\n * at the right time on every task instead of waiting to be asked. Plain text —\n * intentionally no code backticks so the templates stay easy to read.\n */\nconst WORKFLOW_GUIDANCE = [\n 'When a pruned skeleton is not enough to write or change code correctly, expand the exact',\n 'definition with expand_symbol.',\n '',\n 'Call search_symbol_signatures automatically for any identifier you reference that the',\n 'context does not already define, so you always work from exact signatures.',\n '',\n 'Before multi-file edits, reviews, or work on code with uncommitted or staged changes, call',\n 'git_diff_context and use its impact payload (changed files and their callers) as context.',\n '',\n 'Pass activeFiles to get_compressed_code_context when a task spans several files, and',\n 'maxTokens whenever the payload must fit a token budget.',\n].join('\\n');\n\n/** Light guidance used when `.tokenshrinkrc` sets \"autoWorkflow\": false. */\nconst LIGHT_GUIDANCE = [\n 'Use expand_symbol when a pruned body is not enough, git_diff_context for changed or',\n 'multi-file work, and search_symbol_signatures to locate definitions repo-wide.',\n].join('\\n');\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)';\nexport const CLINE_RULE_PATH = RULE_TARGET_PATH.cline;\nexport const CLINE_RULE_SENTINEL = '# auto-generated by token-shrink (cline)';\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${WORKFLOW_GUIDANCE}\n\n${RULE_VERSION_MARKER}\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${WORKFLOW_GUIDANCE}\n\n${RULE_VERSION_MARKER}\n${CLAUDE_RULE_SENTINEL}\n`,\n },\n cline: {\n relPath: CLINE_RULE_PATH,\n sentinel: CLINE_RULE_SENTINEL,\n // No frontmatter -> always-on rule (Cline treats unconditional .clinerules/*.md\n // files as universal rules, applied to every task regardless of active file).\n body: `# token-shrink\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${WORKFLOW_GUIDANCE}\n\n${RULE_VERSION_MARKER}\n${CLINE_RULE_SENTINEL}\n`,\n },\n};\n\nexport interface McpServerOptions {\n /**\n * Project root to watch. When omitted (and the `ROOT` env var is unset) the\n * server runs in auto-detect mode: it locates the project from markers\n * around the process cwd if possible, otherwise lazily from the first tool\n * call's `activeFilePath`.\n */\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 all. */\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 and version-aware:\n * - absent -> create it (tagged with our sentinel + version marker);\n * - has our sentinel AND current version marker -> skip (already ours);\n * - has our sentinel but predates the version marker -> rewrite (upgrade);\n * - present without our 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 // `.tokenshrinkrc.json` \"autoWorkflow\": false switches to lightweight rules.\n const autoWorkflow = loadConfig(root).autoWorkflow !== false;\n const body = autoWorkflow\n ? spec.body\n : spec.body.replace(WORKFLOW_GUIDANCE, LIGHT_GUIDANCE);\n try {\n if (fs.existsSync(rulePath)) {\n const existing = fs.readFileSync(rulePath, 'utf8');\n if (existing.includes(spec.sentinel)) {\n if (existing.includes(RULE_VERSION_MARKER)) {\n return { created: false, skipped: 'exists', filePath: rulePath };\n }\n // Legacy rule we wrote before the version marker existed: upgrade it.\n fs.writeFileSync(rulePath, body, 'utf8');\n return { created: true, skipped: 'none', filePath: rulePath };\n }\n return { created: false, skipped: 'user', filePath: rulePath };\n }\n fs.mkdirSync(path.dirname(rulePath), { recursive: true });\n fs.writeFileSync(rulePath, 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', 'cline'];\n const list = Array.isArray(ruleTarget) ? ruleTarget : [ruleTarget];\n if (list.includes('all' as unknown as RuleTarget)) return ['cursor', 'claude', 'cline'];\n return list;\n}\n\n/** Is `child` inside (or equal to) directory `parent`? */\nfunction isWithin(parent: string, child: string): boolean {\n const rel = path.relative(path.resolve(parent), path.resolve(child));\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/**\n * Normalize the single-file / multi-file active-file inputs into a path list.\n * Exactly one of the two forms may be supplied.\n */\nfunction resolveActiveFiles(\n single: string | undefined,\n many: string[] | undefined,\n): string[] {\n if (many && many.length > 0) {\n if (single) {\n throw new Error('Pass either `activeFilePath` or `activeFiles`, not both.');\n }\n return many;\n }\n if (single) return [single];\n throw new Error('`activeFilePath` or `activeFiles` is required');\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 log = (msg: string) => {\n if (!opts.silent) process.stderr.write(`[token-shrink] ${msg}\\n`);\n };\n const textReply = (text: string) => ({\n content: [{ type: 'text' as const, text }],\n });\n\n // ---------------------------------------------------------------------------\n // Root + watcher lifecycle. An explicit root (--root / ROOT env) warms up\n // immediately. Otherwise the server auto-detects: project markers around the\n // cwd win at startup; if none exist, the root is chosen lazily from the first\n // tool call, and later calls re-point the watcher when the active file moves\n // to a different project.\n // ---------------------------------------------------------------------------\n const explicitRoot = opts.root?.trim() || process.env.ROOT?.trim() || '';\n const autoMode = explicitRoot === '';\n\n let root = '';\n let watcher: WatcherHandle | null = null;\n let searchIndex: SymbolSearch | null = null;\n let lifecycle: Promise<void> = Promise.resolve();\n\n // `.tokenshrinkrc.json` state: re-read at every root attach and hot-reloaded\n // when the file changes under a running server.\n let config: TokenShrinkConfig = { ...EMPTY_CONFIG };\n let configFsw: fs.FSWatcher | null = null;\n let configReloadTimer: NodeJS.Timeout | null = null;\n\n const stopConfigWatch = () => {\n if (configReloadTimer) {\n clearTimeout(configReloadTimer);\n configReloadTimer = null;\n }\n if (configFsw) {\n configFsw.close();\n configFsw = null;\n }\n };\n\n const reloadForRoot = async (r: string) => {\n const next = loadConfig(r, (m) => log(m));\n const changed = JSON.stringify(next) !== JSON.stringify(config);\n config = next;\n if (!changed || !watcher || root !== r) return;\n log('.tokenshrinkrc.json changed — re-indexing with the new rules.');\n stopConfigWatch();\n const old = watcher;\n watcher = null;\n root = '';\n await old.close().catch(() => {});\n await attachWatcher(r, false);\n };\n\n const startConfigWatch = (r: string) => {\n stopConfigWatch();\n const cfgPath = configPathFor(r);\n if (!fs.existsSync(cfgPath)) return;\n try {\n configFsw = fs.watch(cfgPath, () => {\n if (configReloadTimer) clearTimeout(configReloadTimer);\n configReloadTimer = setTimeout(() => {\n void enqueue(() => reloadForRoot(r));\n }, 200);\n });\n } catch {\n /* fs.watch unavailable — config hot-reload disabled for this root */\n }\n };\n\n // Auto-create agent integration rules so the tool is used by default.\n const writeRules = (r: string) => {\n if (opts.createRule === false) return;\n for (const target of resolveTargets(opts.ruleTarget)) {\n const res = createAutoRule(r, 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\n /**\n * Attach a watcher to `r`. When `waitForIndex` is true the returned promise\n * only resolves once the cold tree index finishes (used on the lazy first\n * call so Ring 1 is already warm).\n */\n const attachWatcher = (r: string, waitForIndex: boolean): Promise<void> => {\n stopConfigWatch();\n config = loadConfig(r, (m) => log(m));\n const search = new SymbolSearch();\n const w = createWatcher({\n root: r,\n ignored: opts.ignored,\n config,\n onIndexed: (abs, entry) => {\n if (entry.symbols && entry.symbols.length > 0) search.setFile(abs, entry.symbols);\n else search.removeFile(abs);\n },\n onRemoved: (abs) => search.removeFile(abs),\n });\n searchIndex = search;\n root = r;\n watcher = w;\n writeRules(r);\n log(`Indexing ${r} in the background…`);\n const indexed = w\n .indexAll()\n .then((n) => log(`Indexed ${n} files.`))\n .catch((err: unknown) => log(`Indexing ${r} failed: ${(err as Error)?.message ?? err}`));\n startConfigWatch(r);\n return waitForIndex ? indexed : Promise.resolve();\n };\n\n /** Serialize lifecycle transitions so concurrent tool calls cannot race. */\n const enqueue = (fn: () => Promise<void>): Promise<void> => {\n const run = lifecycle.then(fn);\n lifecycle = run.then(\n () => {},\n () => {},\n );\n return run;\n };\n\n if (explicitRoot) {\n void enqueue(() => attachWatcher(path.resolve(explicitRoot), false));\n } else {\n const fromCwd = detectProjectRoot(process.cwd());\n if (fromCwd) {\n log(`Auto-detected project root ${fromCwd} (from cwd). Pass --root to pin it.`);\n void enqueue(() => attachWatcher(fromCwd, false));\n } else {\n log(\n 'No --root and no project markers around the current directory — ' +\n 'will auto-detect the project from the first tool call.',\n );\n }\n }\n\n /**\n * Ensure a watcher covers `activeFilePath`. No-op once ready; in auto mode a\n * file outside the current root triggers detection of a new root.\n */\n const ensureReadyFor = (activeFilePath: string): Promise<void> =>\n enqueue(async () => {\n const abs = path.resolve(activeFilePath);\n if (watcher && root) {\n if (!autoMode || isWithin(root, abs)) return; // already covered\n const next = detectProjectRoot(abs);\n if (!next || next === root) return; // nothing better to index\n log(`Active file is in a different project (${next}); re-indexing (was ${root}).`);\n await watcher.close().catch(() => {});\n watcher = null;\n root = '';\n }\n if (root) return; // defensive: watcher attached meanwhile\n const detected = detectProjectRoot(abs);\n const target = detected ?? process.cwd();\n if (detected) {\n log(`Auto-detected project root ${target} from ${abs}.`);\n } else {\n log(`No project markers around ${abs}; falling back to ${target}.`);\n }\n await attachWatcher(target, true);\n });\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 one or more files: ' +\n 'each active file’s full source (Ring 0) plus pruned skeletons of their 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 'Use `activeFiles` to pin multiple files as Ring 0 and `maxTokens` to cap the ' +\n 'payload with a relevance-ranked Ring 1.',\n inputSchema: {\n activeFilePath: z\n .string()\n .optional()\n .describe('Path to the file the agent is working on (or use `activeFiles`)'),\n activeFiles: z\n .array(z.string())\n .optional()\n .describe('Multiple files to keep as Ring 0 (full text); mutually exclusive with `activeFilePath`'),\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 maxTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Hard token budget for the whole payload; Ring 1 is relevance-ranked and packed to fit'),\n includeStats: z\n .boolean()\n .optional()\n .describe('Append approximate token-count stats'),\n },\n },\n async ({ activeFilePath, activeFiles, maxSkeletons, maxTokens, includeStats }) => {\n const paths = resolveActiveFiles(activeFilePath, activeFiles);\n // In auto-detect mode each Ring-0 file may live in a different project;\n // ensure the watcher covers every one before assembling.\n for (const p of paths) await ensureReadyFor(p);\n if (!watcher) {\n throw new Error('token-shrink watcher failed to start');\n }\n const result = assembleMany(paths, watcher.cache.entries, {\n maxSkeletons,\n maxTokens,\n includeStats,\n });\n const ts = result.tokenStats;\n const budgetNote =\n ts.budget !== undefined ? ` budget=${ts.budget} trimmed=${ts.trimmed}` : '';\n return {\n content: [\n {\n type: 'text' as const,\n text: result.markdown,\n },\n {\n type: 'text' as const,\n text:\n `[stats] files=${result.activeFilePaths.length} ` +\n `dependencies=${result.included.length} unresolved=${result.unresolved.length} ` +\n `tokens=${ts.totalTokens}${budgetNote}`,\n },\n ],\n };\n },\n );\n\n server.registerTool(\n 'expand_symbol',\n {\n title: 'Expand Symbol',\n description:\n 'Returns the full, un-pruned source of a named definition (function, method, ' +\n 'class, interface, enum, arrow/const function, …) from one file. Use it when ' +\n 'a Ring-1 skeleton is not enough — e.g. you need the exact algorithm inside ' +\n 'a pruned body before writing or changing code.',\n inputSchema: {\n filePath: z.string().describe('Path to the file containing the symbol'),\n symbolName: z\n .string()\n .describe('Name of the definition to expand (exact name preferred; falls back to case-insensitive/substring)'),\n maxMatches: z\n .number()\n .int()\n .min(1)\n .max(20)\n .optional()\n .describe('Maximum matching definitions to return (default 5)'),\n },\n },\n async ({ filePath, symbolName, maxMatches }) => {\n await ensureReadyFor(filePath);\n const abs = path.resolve(filePath);\n let source: string;\n try {\n source = fs.readFileSync(abs, 'utf8');\n } catch {\n return textReply(`File not found or unreadable: ${filePath}`);\n }\n const spec = languageForFile(abs);\n if (!spec) {\n return textReply(`No token-shrink grammar for file type: ${filePath}`);\n }\n const { symbols } = await analyze(abs, source, { skipPrune: true });\n if (symbols.length === 0) {\n return textReply(\n `No parseable definitions found in ${filePath} — the grammar may be unavailable ` +\n '(first run offline) or the language exposes no name-carrying definitions yet.',\n );\n }\n const matches = matchSymbols(symbols, symbolName).slice(0, maxMatches ?? 5);\n if (matches.length === 0) {\n const names = [...new Set(symbols.map((s) => s.name))].slice(0, 12).join(', ');\n return textReply(\n `No symbol named \"${symbolName}\" in ${filePath}.` +\n (names ? ` Other definitions there: ${names}.` : ''),\n );\n }\n const fence = path.extname(abs).replace(/^\\./, '') || 'text';\n const parts = matches.map((m) => {\n const body = source.slice(m.start, m.end).trim();\n return (\n `### ${m.name} (${m.kind}) — ${abs}:${m.line}` +\n '\\n\\n```' +\n fence +\n '\\n' +\n body +\n '\\n```\\n'\n );\n });\n const disambig =\n matches.length > 1\n ? `\\n_Multiple definitions matched (${matches.length}); each is shown above._`\n : '';\n return textReply(parts.join('\\n') + disambig);\n },\n );\n\n server.registerTool(\n 'git_diff_context',\n {\n title: 'Git Diff Context',\n description:\n 'Builds an impact-analysis payload from git changes: every changed file is ' +\n 'kept as Ring 0 (full code), their imports AND the files that import them ' +\n '(file-level callers) are attached as pruned Ring-1 skeletons. Use for PR ' +\n 'reviews, regression fixes and multi-file tasks where no single \"active file\" exists.',\n inputSchema: {\n scope: z\n .enum(['worktree', 'staged', 'branch'])\n .optional()\n .describe(\"Diff scope: 'worktree' (default, staged+unstaged), 'staged', or 'branch' (base...head)\"),\n base: z.string().optional().describe('Base ref for scope=branch (default HEAD~1)'),\n head: z.string().optional().describe('Head ref for scope=branch (default HEAD)'),\n includeUntracked: z\n .boolean()\n .optional()\n .describe('Include untracked files (worktree scope only)'),\n maxFiles: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Maximum changed files to include (default 30)'),\n maxImporters: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Maximum importer skeletons to append (default 20)'),\n maxSkeletons: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe('Cap on dependency skeletons per payload'),\n maxTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Hard token budget for the whole payload'),\n includeStats: z.boolean().optional().describe('Append approximate token-count stats'),\n },\n },\n async ({\n scope,\n base,\n head,\n includeUntracked,\n maxFiles,\n maxImporters,\n maxSkeletons,\n maxTokens,\n includeStats,\n }) => {\n // The git root is the server root; in auto mode detect from cwd until a\n // tool call establishes the project.\n await ensureReadyFor(process.cwd());\n if (!watcher || !root) {\n throw new Error('token-shrink watcher failed to start');\n }\n const repoRoot = root;\n const changedResult = await gitChangedFiles(repoRoot, {\n scope: (scope as GitDiffScope) ?? 'worktree',\n base,\n head,\n includeUntracked,\n } satisfies GitChangedOptions);\n if (changedResult.error) {\n return textReply(`git error: ${changedResult.error}`);\n }\n if (changedResult.files.length === 0) {\n return textReply('No changed files (clean worktree, or empty diff for the requested scope).');\n }\n const fileCap = maxFiles ?? 30;\n const changed = changedResult.files.slice(0, fileCap);\n const filesTruncated = changedResult.files.length > changed.length;\n\n // Warm not-yet-indexed changed files so Ring-1 edges are accurate.\n for (const abs of changed) {\n if (!watcher.cache.entries.has(abs)) {\n try {\n await watcher.index(abs);\n } catch {\n /* unparseable file — skip */\n }\n }\n }\n\n const assembled = assembleMany(changed, watcher.cache.entries, {\n maxSkeletons,\n maxTokens,\n includeStats,\n });\n\n // Reverse edges: files that import the changed files (file-level callers).\n const changedSet = new Set(changed);\n const importerOf = new Map<string, string[]>();\n for (const [fileAbs, entry] of watcher.cache.entries) {\n for (const imp of entry.imports) {\n if (!changedSet.has(imp)) continue;\n const list = importerOf.get(imp) ?? [];\n list.push(fileAbs);\n importerOf.set(imp, list);\n }\n }\n const importerList = [...new Set([...importerOf.values()].flat())].filter(\n (f) => !changedSet.has(f),\n );\n const importerCap = maxImporters ?? 20;\n const importers = importerList.slice(0, importerCap);\n const importersTruncated = importerList.length > importers.length;\n\n const relLabel = (abs: string) => {\n const rel = path.relative(repoRoot, abs);\n return rel && !rel.startsWith('..') ? rel : abs;\n };\n const fence = (abs: string) => path.extname(abs).replace(/^\\./, '') || 'text';\n\n const parts: string[] = [];\n parts.push(\n `# Git Impact Context (${changed.length} changed file${changed.length === 1 ? '' : 's'})`,\n '',\n );\n parts.push(`- changed files: ${changed.map(relLabel).join(', ')}`);\n if (importers.length > 0) {\n parts.push(`- importing files (callers): ${importers.map(relLabel).join(', ')}`);\n }\n parts.push('', '---', '');\n parts.push('## Changed files — full code', '');\n for (const abs of changed) {\n parts.push(`### \\`${relLabel(abs)}\\``, '');\n let source = '';\n try {\n source = fs.readFileSync(abs, 'utf8');\n } catch {\n /* file vanished between listing and read */\n }\n parts.push(`\\`\\`\\`${fence(abs)}`, source.trim() || '(unreadable file)', '```', '');\n }\n parts.push(`## Ring 1 — Pruned dependencies (${assembled.included.length})`, '');\n parts.push('', 'Implementation bodies removed; type signatures, interfaces and exports retained.', '');\n if (assembled.included.length === 0) {\n parts.push('_No local dependency skeletons available._', '');\n }\n for (const inc of assembled.included) {\n const entry = watcher.cache.entries.get(inc.filePath);\n const label = relLabel(inc.filePath);\n parts.push(`### \\`${label}\\``, '');\n if (entry) {\n parts.push(`\\`\\`\\`${fence(inc.filePath)}`, entry.skeleton.trim(), '```', '');\n } else {\n parts.push('_Unindexed file._', '');\n }\n parts.push('');\n }\n if (assembled.tokenStats.budget !== undefined && assembled.tokenStats.trimmed > 0) {\n parts.push(\n `_Note: token budget of ${assembled.tokenStats.budget} excluded ` +\n `${assembled.tokenStats.trimmed} lower-priority dependencies._`,\n '',\n );\n }\n\n if (importers.length > 0) {\n parts.push(`## Ring 2 — Files importing the diff (${importers.length})`, '');\n parts.push('', 'Pruned skeletons of modules that call into the changed files.', '');\n for (const abs of importers) {\n const entry = watcher.cache.entries.get(abs);\n parts.push(`### \\`${relLabel(abs)}\\``, '');\n if (entry) {\n parts.push(`\\`\\`\\`${fence(abs)}`, entry.skeleton.trim(), '```', '');\n } else {\n parts.push('_Unindexed file._', '');\n }\n parts.push('');\n }\n if (importersTruncated) {\n parts.push(\n `_…and ${importerList.length - importers.length} more importing files (raise maxImporters)._`,\n '',\n );\n }\n }\n if (filesTruncated) {\n parts.push(\n `_Note: capped to ${fileCap} changed files (${changedResult.files.length} total); ` +\n 'raise maxFiles to include more._',\n '',\n );\n }\n if (assembled.unresolved.length > 0) {\n parts.push('## Unresolved imports', '');\n for (const u of assembled.unresolved) parts.push(`- \\`${u}\\``);\n parts.push('');\n }\n\n const ts = assembled.tokenStats;\n const budgetNote =\n ts.budget !== undefined ? ` budget=${ts.budget} trimmed=${ts.trimmed}` : '';\n const stats =\n `[git-stats] files=${changed.length} ring1=${assembled.included.length} ` +\n `importers=${importers.length} unresolved=${assembled.unresolved.length} tokens=${ts.totalTokens}${budgetNote}`;\n return {\n content: [\n { type: 'text' as const, text: parts.join('\\n') },\n { type: 'text' as const, text: stats },\n ],\n };\n },\n );\n\n server.registerTool(\n 'search_symbol_signatures',\n {\n title: 'Search Symbol Signatures',\n description:\n 'Fast, repo-wide lookup of named definitions (functions, methods, classes, ' +\n 'interfaces, enums, …). Returns compact `file:line — signature` lines instead ' +\n 'of raw search hits. Use it to discover where a symbol lives and what its ' +\n 'exact signature is before reading or editing code.',\n inputSchema: {\n query: z\n .string()\n .describe('Search text (matched against symbol names; falls back to signatures)'),\n maxResults: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Maximum results to return (default 10)'),\n kind: z\n .enum(['function', 'method', 'arrow', 'class', 'interface', 'enum', 'type', 'other'])\n .optional()\n .describe('Only return definitions of this kind'),\n },\n },\n async ({ query, maxResults, kind }) => {\n await ensureReadyFor(process.cwd());\n if (!searchIndex) {\n throw new Error('token-shrink symbol index failed to start');\n }\n // Cold lazy build: if the background index has not finished yet, load\n // whatever the cache already holds so the first search still answers.\n if (searchIndex.size === 0 && watcher && watcher.cache.entries.size > 0) {\n searchIndex.loadCache(watcher.cache.entries);\n }\n const hits = searchIndex.search(query, {\n maxResults: maxResults ?? 10,\n kind: kind as SymbolKind | undefined,\n });\n if (hits.length === 0) {\n return textReply(`No symbols match \"${query}\". Try a different name or kind.`);\n }\n const lines = hits.map((h) => `- \\`${h.label}\\``);\n return textReply(\n `${lines.join('\\n')}\\n\\n_Found ${hits.length} symbol${hits.length === 1 ? '' : 's'} ` +\n `matching \"${query}\"._`,\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, not when imported as a\n// library. Guard against both the source filenames and the tsup bundles:\n// `dist/mcp.cjs` (used by the npm `token-shrink-mcp` bin). `realpathSync`\n// resolves the npm bin symlink, so `token-shrink-mcp` -> `dist/mcp.cjs` is\n// detected as `mcp.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}\nconst invokedAsMcp =\n argv1 === 'mcp.js' || argv1 === 'mcp.mjs' ||\n argv1 === 'mcp.cjs' || argv1 === 'mcp.ts' ||\n argv1Real === 'mcp.js' || argv1Real === 'mcp.mjs' ||\n argv1Real === 'mcp.cjs' || argv1Real === 'mcp.ts';\nif (invokedAsMcp) {\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|cline|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' || v === 'cline',\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","/**\n * Project-root auto-detection for zero-config (no `--root`) mode.\n *\n * The MCP server cannot always know its project at startup: clients spawn\n * stdio servers from directories they choose, and shared/global configs have no\n * project at all. When no explicit root is supplied, these helpers locate the\n * repository by walking up from a known path (the process cwd, or the active\n * file of a tool call) until a VCS directory or a project manifest is found.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** VCS dirs mark the true repository boundary — the strongest signal. */\nexport const VCS_MARKER_DIRS = ['.git', '.hg', '.svn'] as const;\n\n/** Manifest files that mark a project boundary when no VCS dir exists. */\nexport const PROJECT_MANIFEST_FILES = [\n // JavaScript / TypeScript\n 'package.json',\n 'tsconfig.json',\n // Python\n 'pyproject.toml',\n 'setup.py',\n 'setup.cfg',\n 'requirements.txt',\n // Go / Rust / Dart / Swift\n 'go.mod',\n 'Cargo.toml',\n 'pubspec.yaml',\n 'Package.swift',\n // Java / Kotlin\n 'pom.xml',\n 'build.gradle',\n 'build.gradle.kts',\n 'settings.gradle',\n 'settings.gradle.kts',\n // PHP / Ruby / Elixir\n 'composer.json',\n 'Gemfile',\n 'mix.exs',\n] as const;\n\nconst MANIFEST_FILE_SET: ReadonlySet<string> = new Set(PROJECT_MANIFEST_FILES);\n\n/** Ceiling on upward directory walks (fs roots are deep but bounded). */\nconst MAX_WALK_DEPTH = 64;\n\n/**\n * Find the project root that `fromPath` belongs to, or `null` when none can be\n * determined. `fromPath` may be a file or directory (existing or not).\n *\n * Walk-up rules:\n * - the first ancestor containing a VCS dir (`.git`/`.hg`/`.svn`) wins — it is\n * the true repository boundary, even inside a monorepo sub-package;\n * - otherwise the deepest ancestor containing a project manifest\n * (`package.json`, `pyproject.toml`, `go.mod`, …) is returned;\n * - otherwise `null`, meaning the tree holds no recognizable project markers.\n */\nexport function detectProjectRoot(fromPath: string): string | null {\n const resolved = path.resolve(fromPath);\n let dir = isDirectory(resolved) ? resolved : path.dirname(resolved);\n let nearestManifest: string | null = null;\n\n for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {\n const names = readDirNames(dir);\n if (names) {\n if (VCS_MARKER_DIRS.some((vcs) => names.has(vcs))) return dir;\n if (nearestManifest === null && hasManifest(names)) nearestManifest = dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break; // reached the filesystem root\n dir = parent;\n }\n return nearestManifest;\n}\n\n/** Is `p` an existing directory (ENOENT-safe)? */\nfunction isDirectory(p: string): boolean {\n try {\n return fs.statSync(p).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** Read a directory's entry names, or `null` when unreadable. */\nfunction readDirNames(dir: string): ReadonlySet<string> | null {\n try {\n return new Set(fs.readdirSync(dir));\n } catch {\n return null; // permission errors / vanished dirs mid-walk\n }\n}\n\nfunction hasManifest(names: ReadonlySet<string>): boolean {\n for (const name of names) {\n if (MANIFEST_FILE_SET.has(name)) return true;\n }\n return false;\n}\n","/**\n * In-memory symbol signature index for `search_symbol_signatures`.\n *\n * Zero-dependency alternative to SQLite FTS5: we index only symbol metadata\n * (names + signature lines) produced during the tree-sitter analyze pass, so\n * lookups stay well under a millisecond at repository scale without adding a\n * native module to the dependency tree.\n *\n * The index is kept fresh by the watcher: files are added/removed as chokidar\n * events and the analyze pass run.\n */\n\nimport type { SymbolInfo, SymbolKind } from '../parser/symbols.js';\nimport type { CacheEntry } from '../watcher/sync.js';\n\nexport interface SymbolDoc extends SymbolInfo {\n /** Absolute path of the containing file. */\n filePath: string;\n}\n\nexport interface SymbolHit extends SymbolDoc {\n /** Higher is better. */\n score: number;\n /** Human label like `file.ts:12 — fn(a: number): number`. */\n label: string;\n}\n\ntype ScoredHit = SymbolDoc & { score: number };\n\n/** Split an identifier into searchable words (camelCase + snake_case aware). */\nfunction words(text: string): string[] {\n const out = new Set<string>();\n for (const part of text.split(/[^A-Za-z0-9_$]+/)) {\n if (!part) continue;\n // camelCase / PascalCase boundaries.\n for (const seg of part.split(/(?<=[a-z0-9])(?=[A-Z])/)) {\n const w = seg.toLowerCase();\n if (w) out.add(w);\n }\n // snake_case parts.\n for (const seg of part.split('_')) {\n const w = seg.toLowerCase();\n if (w) out.add(w);\n }\n }\n return [...out];\n}\n\nexport class SymbolSearch {\n private docs: SymbolDoc[] = [];\n private byFile = new Map<string, SymbolDoc[]>();\n private inverted = new Map<string, number[]>();\n\n get size(): number {\n return this.docs.length;\n }\n\n /** Replace the docs for one file (or remove when `symbols` is empty). */\n setFile(filePath: string, symbols: SymbolInfo[]): void {\n this.removeFile(filePath);\n if (symbols.length === 0) return;\n const docs: SymbolDoc[] = symbols.map((s) => ({ ...s, filePath }));\n const ids = docs.map((d) => {\n const id = this.docs.length;\n this.docs.push(d);\n for (const w of words(`${d.name}`)) {\n const list = this.inverted.get(w) ?? [];\n list.push(id);\n this.inverted.set(w, list);\n }\n return id;\n });\n this.byFile.set(filePath, docs);\n void ids; // ids are implicit in `this.docs`\n }\n\n removeFile(filePath: string): void {\n const docs = this.byFile.get(filePath);\n if (!docs) return;\n const removed = new Set(docs);\n // Rebuild the arrays from scratch: file-level churn is rare enough that\n // this stays far cheaper than a persistent per-doc tombstones scheme.\n this.docs = this.docs.filter((d) => !removed.has(d));\n this.byFile.delete(filePath);\n this.rebuildInverted();\n }\n\n /** Bulk-load a whole cache (used at attach time and cold lazy builds). */\n loadCache(entries: ReadonlyMap<string, CacheEntry>): void {\n this.docs = [];\n this.byFile.clear();\n for (const [abs, entry] of entries) {\n if (!entry.symbols || entry.symbols.length === 0) continue;\n const docs: SymbolDoc[] = entry.symbols.map((s) => ({ ...s, filePath: abs }));\n this.byFile.set(abs, docs);\n this.docs.push(...docs);\n }\n this.rebuildInverted();\n }\n\n /** Ranked symbol hits for `query`. */\n search(\n query: string,\n opts: { maxResults?: number; kind?: SymbolKind } = {},\n ): SymbolHit[] {\n const maxResults = opts.maxResults ?? 10;\n const q = query.trim().toLowerCase();\n if (!q) return [];\n\n const queryWords = words(q);\n let candidates: SymbolDoc[];\n if (queryWords.length > 0) {\n const ids = new Set<number>();\n for (const w of queryWords) {\n const post = this.inverted.get(w);\n if (post) for (const id of post) ids.add(id);\n }\n candidates = [...ids].map((id) => this.docs[id]);\n } else {\n candidates = this.docs;\n }\n if (opts.kind) candidates = candidates.filter((d) => d.kind === opts.kind);\n\n const scored = candidates\n .map((d) => this.score(d, q, queryWords))\n .filter((s): s is ScoredHit => s !== null)\n .sort((a, b) => b.score - a.score || a.line - b.line)\n .slice(0, maxResults);\n\n return scored.map((s) => ({ ...s, label: this.label(s) }));\n }\n\n private score(\n d: SymbolDoc,\n q: string,\n queryWords: string[],\n ): ScoredHit | null {\n const name = d.name.toLowerCase();\n let score = 0;\n if (name === q) score += 100;\n if (name.startsWith(q)) score += 60;\n if (name.includes(q)) score += 30;\n if ((d.signature ?? '').toLowerCase().includes(q)) score += 8;\n for (const w of queryWords) {\n if (name.includes(w)) score += 4;\n if ((d.signature ?? '').toLowerCase().includes(w)) score += 1;\n }\n if (score <= 0) return null;\n return { ...d, score };\n }\n\n private label(d: SymbolDoc): string {\n const sig = d.signature && d.signature.length > 0 ? ` — ${d.signature}` : '';\n return `${d.filePath}:${d.line}${sig}`;\n }\n\n private rebuildInverted(): void {\n this.inverted.clear();\n this.docs.forEach((d, id) => {\n for (const w of words(d.name)) {\n const list = this.inverted.get(w) ?? [];\n list.push(id);\n this.inverted.set(w, list);\n }\n });\n }\n}\n\n","/**\n * Thin `git` plumbing helpers for the `git_diff_context` MCP tool. Uses the\n * system `git` binary via spawn (no native deps) and always runs with\n * `--no-pager` + `LC_ALL=C` so output is deterministic and parseable.\n */\n\nimport { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nexport type GitDiffScope = 'worktree' | 'staged' | 'branch';\n\nexport interface GitChangedOptions {\n scope: GitDiffScope;\n /** Base ref for `scope: 'branch'` (e.g. `main`). Defaults to `HEAD~1`. */\n base?: string;\n /** Head ref for `scope: 'branch'`. Defaults to `HEAD`. */\n head?: string;\n /** Include untracked files (worktree scope only). */\n includeUntracked?: boolean;\n}\n\nexport interface GitChangedResult {\n /** Absolute paths of changed files that exist on disk. */\n files: string[];\n /** Non-empty when git could not be satisfied (not a repo, bad ref, …). */\n error?: string;\n}\n\nfunction runGit(root: string, args: string[]): Promise<{ ok: boolean; out: string; err: string }> {\n return new Promise((resolve) => {\n const child = spawn('git', ['--no-pager', ...args], {\n cwd: root,\n env: { ...process.env, LC_ALL: 'C' },\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let out = '';\n let err = '';\n child.stdout.on('data', (d) => {\n out += d;\n });\n child.stderr.on('data', (d) => {\n err += d;\n });\n child.on('error', (e) => resolve({ ok: false, out: '', err: e.message }));\n child.on('close', (code) => resolve({ ok: code === 0, out, err }));\n });\n}\n\n/** Split git name-only output into relative paths. */\nfunction parseNames(out: string): string[] {\n return out\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n}\n\nfunction isFatal(err: string): string | undefined {\n if (!err) return undefined;\n const e = err.trim();\n if (/not a git repository|fatal:/i.test(e)) return e;\n return undefined;\n}\n\n/**\n * List files changed in the repository at `root`. Paths are returned absolute\n * and filtered to files that still exist on disk.\n */\nexport async function gitChangedFiles(\n root: string,\n opts: GitChangedOptions,\n): Promise<GitChangedResult> {\n const scope = opts.scope ?? 'worktree';\n const filter = '--diff-filter=ACMRT';\n\n let relative: string[] = [];\n if (scope === 'staged') {\n const r = await runGit(root, ['diff', '--cached', '--name-only', filter]);\n const fatal = isFatal(r.err);\n if (!r.ok) return { files: [], ...(fatal ? { error: fatal } : {}) };\n relative = parseNames(r.out);\n } else if (scope === 'branch') {\n const base = opts.base ?? 'HEAD~1';\n const head = opts.head ?? 'HEAD';\n const r = await runGit(root, ['diff', '--name-only', `${base}...${head}`, filter]);\n const fatal = isFatal(r.err);\n if (!r.ok) return { files: [], ...(fatal ? { error: fatal } : {}) };\n relative = parseNames(r.out);\n } else {\n // worktree = staged + unstaged (merged, deduped).\n const [unstaged, staged] = await Promise.all([\n runGit(root, ['diff', '--name-only', filter]),\n runGit(root, ['diff', '--cached', '--name-only', filter]),\n ]);\n const fatal = isFatal(unstaged.err) ?? isFatal(staged.err);\n if (!unstaged.ok && !staged.ok) {\n return { files: [], ...(fatal ? { error: fatal } : {}) };\n }\n const merged = new Set([...parseNames(unstaged.out), ...parseNames(staged.out)]);\n if (opts.includeUntracked) {\n const ut = await runGit(root, ['ls-files', '--others', '--exclude-standard']);\n for (const f of parseNames(ut.out)) merged.add(f);\n }\n relative = [...merged];\n }\n\n const files = relative\n .map((rel) => path.resolve(root, rel))\n .filter((abs) => {\n try {\n return fs.statSync(abs).isFile();\n } catch {\n return false; // deleted in the meantime / rename source\n }\n });\n\n return { files };\n}\n"],"mappings":"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","names":["fs","path","path","fs","path","fs"]}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as chokidar from 'chokidar';
|
|
2
|
+
import { Matcher, FSWatcher } from 'chokidar';
|
|
3
|
+
import { SyntaxNode } from 'web-tree-sitter';
|
|
4
|
+
import * as fastify from 'fastify';
|
|
5
|
+
import * as http from 'http';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Symbol extraction from a parsed tree. One tree-sitter parse yields every
|
|
9
|
+
* named definition (function/class/interface/…) with its byte range, so the
|
|
10
|
+
* MCP server can:
|
|
11
|
+
* - `expand_symbol`: return a specific definition's full, un-pruned body;
|
|
12
|
+
* - `search_symbol_signatures`: index names + signature lines for fast lookup.
|
|
13
|
+
*
|
|
14
|
+
* Node types are matched by name across grammars, and definitions are only
|
|
15
|
+
* kept when the grammar exposes a `name` field (verified for TS/JS/TSX/JSX,
|
|
16
|
+
* Python, Go, Rust, Kotlin, Dart, Swift, Java, PHP). Grammars without a
|
|
17
|
+
* `name` field (e.g. C/C++ `function_definition`) simply contribute nothing.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
type SymbolKind = 'function' | 'method' | 'arrow' | 'class' | 'interface' | 'enum' | 'type' | 'other';
|
|
21
|
+
interface SymbolInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
kind: SymbolKind;
|
|
24
|
+
/** 1-based line of the definition start. */
|
|
25
|
+
line: number;
|
|
26
|
+
/** Byte range in the original source (the full definition, body included). */
|
|
27
|
+
start: number;
|
|
28
|
+
end: number;
|
|
29
|
+
/** First line of the definition (trimmed, capped) for search previews. */
|
|
30
|
+
signature?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Walk `root` and collect every named definition with its byte range.
|
|
34
|
+
* `source` is only needed to build signature/line previews.
|
|
35
|
+
*/
|
|
36
|
+
declare function collectSymbols(root: SyntaxNode, source: string): SymbolInfo[];
|
|
37
|
+
/**
|
|
38
|
+
* Resolve `query` to matching symbols. Exact name match wins; falls back to
|
|
39
|
+
* case-insensitive exact, then substring. `kind` narrows the candidates.
|
|
40
|
+
*/
|
|
41
|
+
declare function matchSymbols(symbols: SymbolInfo[], query: string, kind?: SymbolKind): SymbolInfo[];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* `.tokenshrinkrc.json` support — developer-level customization.
|
|
45
|
+
*
|
|
46
|
+
* Supported keys (all optional arrays of strings):
|
|
47
|
+
* - ignorePatterns: glob patterns of paths that are never indexed/watched;
|
|
48
|
+
* - keepUnpruned: glob patterns of files to index but never prune;
|
|
49
|
+
* - preserveAnnotations: markers (e.g. `@keepContext`, `@api`) that exempt a
|
|
50
|
+
* definition (and everything nested in it) from pruning.
|
|
51
|
+
*
|
|
52
|
+
* The config file lives at the repository root (the auto-detected root when no
|
|
53
|
+
* `--root` is given). Invalid JSON never crashes the server — it logs a warning
|
|
54
|
+
* and falls back to empty defaults.
|
|
55
|
+
*/
|
|
56
|
+
declare const CONFIG_FILE_NAME = ".tokenshrinkrc.json";
|
|
57
|
+
interface TokenShrinkConfig {
|
|
58
|
+
/** Glob patterns of paths that should never be indexed or watched. */
|
|
59
|
+
ignorePatterns: string[];
|
|
60
|
+
/** Glob patterns of files to index but never prune (full Ring-1 text). */
|
|
61
|
+
keepUnpruned: string[];
|
|
62
|
+
/** Annotation markers (e.g. `@keepContext`) that exempt a definition from pruning. */
|
|
63
|
+
preserveAnnotations: string[];
|
|
64
|
+
/**
|
|
65
|
+
* When false, the generated agent rule carries only lightweight guidance and
|
|
66
|
+
* the model decides when to call the auxiliary tools on its own. Default
|
|
67
|
+
* (true / unset): rules choreograph the tools automatically each task.
|
|
68
|
+
*/
|
|
69
|
+
autoWorkflow?: boolean;
|
|
70
|
+
}
|
|
71
|
+
declare const EMPTY_CONFIG: TokenShrinkConfig;
|
|
72
|
+
declare function configPathFor(root: string): string;
|
|
73
|
+
/** Parse + validate the config at `root`, tolerating any JSON shape. */
|
|
74
|
+
declare function loadConfig(root: string, warn?: (msg: string) => void): TokenShrinkConfig;
|
|
75
|
+
/** True when the (slash-normalized) `file` matches any `pattern`. */
|
|
76
|
+
declare function matchesAny(file: string, patterns: string[]): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Glob matcher with `**`, `*`, `?` and `[...]` support. Patterns that contain
|
|
79
|
+
* no glob metacharacters also match as a path suffix (a bare filename like
|
|
80
|
+
* `global.d.ts` matches any directory containing it).
|
|
81
|
+
*/
|
|
82
|
+
declare function matchesGlob(file: string, pattern: string): boolean;
|
|
83
|
+
/** Compile `**`/`*`/`?`/`[...]` glob into a `/`-normalized regex. */
|
|
84
|
+
declare function globToRegExp(glob: string): RegExp;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Incremental synchronization layer (Phase 3).
|
|
88
|
+
*
|
|
89
|
+
* - Watches the repository with chokidar (ignoring vendor/build dirs).
|
|
90
|
+
* - On add/change, hashes the file and, if the hash changed, re-prunes it and
|
|
91
|
+
* updates the in-memory graph cache.
|
|
92
|
+
* - Extracts import/require specifiers from each file and normalizes relative
|
|
93
|
+
* and aliased paths to absolute file paths on disk.
|
|
94
|
+
*
|
|
95
|
+
* The graph cache is shared with the Context Assembler, which reads ring-1
|
|
96
|
+
* skeletons out of it.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
/** Default paths that will never be indexed or watched. */
|
|
100
|
+
declare const DEFAULT_IGNORED: RegExp[];
|
|
101
|
+
interface CacheEntry {
|
|
102
|
+
/** sha1 of the last-indexed file content. */
|
|
103
|
+
hash: string;
|
|
104
|
+
/** Pruned skeleton for this file. */
|
|
105
|
+
skeleton: string;
|
|
106
|
+
/** The language name used to prune it (or null if unsupported). */
|
|
107
|
+
language: string | null;
|
|
108
|
+
/** Absolute paths of the files this file imports. */
|
|
109
|
+
imports: string[];
|
|
110
|
+
/** Named definitions found while indexing (for expand_symbol / search). */
|
|
111
|
+
symbols?: SymbolInfo[];
|
|
112
|
+
}
|
|
113
|
+
type GraphCache = Map<string, CacheEntry>;
|
|
114
|
+
declare class ContextCache {
|
|
115
|
+
readonly entries: GraphCache;
|
|
116
|
+
private initPromise;
|
|
117
|
+
ensureInit(): Promise<void>;
|
|
118
|
+
/** Returns the cached skeleton for a file, if present. */
|
|
119
|
+
getSkeleton(filePath: string): CacheEntry | null;
|
|
120
|
+
get imports(): GraphCache;
|
|
121
|
+
}
|
|
122
|
+
/** Compute a sha1 of a string. */
|
|
123
|
+
declare function hashOf(text: string): string;
|
|
124
|
+
/**
|
|
125
|
+
* Extract import/require specifiers from source text using a robust,
|
|
126
|
+
* language-agnostic regex (AST-based import queries are grammar-fragile and
|
|
127
|
+
* occasionally malformed; regex covers the common import forms across JS/TS,
|
|
128
|
+
* Python, Go, Rust, Dart, Swift, Java, Kotlin, PHP, C/C++).
|
|
129
|
+
* Returns the matched specifier strings (may be relative or absolute).
|
|
130
|
+
*/
|
|
131
|
+
declare function extractImports(_filePath: string, source: string): string[];
|
|
132
|
+
/** Normalize a specifier to an absolute file path when it resolves locally. */
|
|
133
|
+
declare function resolveImport(importer: string, specifier: string, root: string): string | null;
|
|
134
|
+
interface SyncOptions {
|
|
135
|
+
root: string;
|
|
136
|
+
ignored?: Matcher[];
|
|
137
|
+
/** Optional `.tokenshrinkrc.json` settings. */
|
|
138
|
+
config?: TokenShrinkConfig;
|
|
139
|
+
onIndexed?: (filePath: string, entry: CacheEntry) => void;
|
|
140
|
+
/** Called when a watched file disappears from disk (cache entry dropped). */
|
|
141
|
+
onRemoved?: (filePath: string) => void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Watch a project root and keep the graph cache fresh. Returns the cache and
|
|
145
|
+
* a close() handle. `prune` is awaited per change to keep hot-reload latency
|
|
146
|
+
* predictable.
|
|
147
|
+
*/
|
|
148
|
+
declare function createWatcher(opts: SyncOptions): {
|
|
149
|
+
cache: ContextCache;
|
|
150
|
+
watcher: FSWatcher;
|
|
151
|
+
/** Index an existing file right now (bypasses the watcher). */
|
|
152
|
+
index: (filePath: string) => Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Index the whole tree once (cold start). Returns the number of files
|
|
155
|
+
* successfully indexed.
|
|
156
|
+
*/
|
|
157
|
+
indexAll(): Promise<number>;
|
|
158
|
+
close: () => Promise<void>;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
interface CliOptions {
|
|
162
|
+
port?: number;
|
|
163
|
+
host?: string;
|
|
164
|
+
root?: string;
|
|
165
|
+
ignored?: Matcher[];
|
|
166
|
+
silent?: boolean;
|
|
167
|
+
}
|
|
168
|
+
/** Start the Fastify server; returns the running instance + watcher handle. */
|
|
169
|
+
declare function startServer(opts?: CliOptions): Promise<{
|
|
170
|
+
app: fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault> & PromiseLike<fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>> & {
|
|
171
|
+
__linterBrands: "SafePromiseLike";
|
|
172
|
+
};
|
|
173
|
+
watcher: {
|
|
174
|
+
cache: ContextCache;
|
|
175
|
+
watcher: chokidar.FSWatcher;
|
|
176
|
+
index: (filePath: string) => Promise<void>;
|
|
177
|
+
indexAll(): Promise<number>;
|
|
178
|
+
close: () => Promise<void>;
|
|
179
|
+
};
|
|
180
|
+
}>;
|
|
181
|
+
|
|
182
|
+
export { type CacheEntry as C, DEFAULT_IGNORED as D, EMPTY_CONFIG as E, type GraphCache as G, type SymbolInfo as S, type TokenShrinkConfig as T, type SymbolKind as a, CONFIG_FILE_NAME as b, type CliOptions as c, type SyncOptions as d, collectSymbols as e, configPathFor as f, createWatcher as g, extractImports as h, globToRegExp as i, hashOf as j, matchesAny as k, loadConfig as l, matchSymbols as m, matchesGlob as n, resolveImport as r, startServer as s };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as chokidar from 'chokidar';
|
|
2
|
+
import { Matcher, FSWatcher } from 'chokidar';
|
|
3
|
+
import { SyntaxNode } from 'web-tree-sitter';
|
|
4
|
+
import * as fastify from 'fastify';
|
|
5
|
+
import * as http from 'http';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Symbol extraction from a parsed tree. One tree-sitter parse yields every
|
|
9
|
+
* named definition (function/class/interface/…) with its byte range, so the
|
|
10
|
+
* MCP server can:
|
|
11
|
+
* - `expand_symbol`: return a specific definition's full, un-pruned body;
|
|
12
|
+
* - `search_symbol_signatures`: index names + signature lines for fast lookup.
|
|
13
|
+
*
|
|
14
|
+
* Node types are matched by name across grammars, and definitions are only
|
|
15
|
+
* kept when the grammar exposes a `name` field (verified for TS/JS/TSX/JSX,
|
|
16
|
+
* Python, Go, Rust, Kotlin, Dart, Swift, Java, PHP). Grammars without a
|
|
17
|
+
* `name` field (e.g. C/C++ `function_definition`) simply contribute nothing.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
type SymbolKind = 'function' | 'method' | 'arrow' | 'class' | 'interface' | 'enum' | 'type' | 'other';
|
|
21
|
+
interface SymbolInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
kind: SymbolKind;
|
|
24
|
+
/** 1-based line of the definition start. */
|
|
25
|
+
line: number;
|
|
26
|
+
/** Byte range in the original source (the full definition, body included). */
|
|
27
|
+
start: number;
|
|
28
|
+
end: number;
|
|
29
|
+
/** First line of the definition (trimmed, capped) for search previews. */
|
|
30
|
+
signature?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Walk `root` and collect every named definition with its byte range.
|
|
34
|
+
* `source` is only needed to build signature/line previews.
|
|
35
|
+
*/
|
|
36
|
+
declare function collectSymbols(root: SyntaxNode, source: string): SymbolInfo[];
|
|
37
|
+
/**
|
|
38
|
+
* Resolve `query` to matching symbols. Exact name match wins; falls back to
|
|
39
|
+
* case-insensitive exact, then substring. `kind` narrows the candidates.
|
|
40
|
+
*/
|
|
41
|
+
declare function matchSymbols(symbols: SymbolInfo[], query: string, kind?: SymbolKind): SymbolInfo[];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* `.tokenshrinkrc.json` support — developer-level customization.
|
|
45
|
+
*
|
|
46
|
+
* Supported keys (all optional arrays of strings):
|
|
47
|
+
* - ignorePatterns: glob patterns of paths that are never indexed/watched;
|
|
48
|
+
* - keepUnpruned: glob patterns of files to index but never prune;
|
|
49
|
+
* - preserveAnnotations: markers (e.g. `@keepContext`, `@api`) that exempt a
|
|
50
|
+
* definition (and everything nested in it) from pruning.
|
|
51
|
+
*
|
|
52
|
+
* The config file lives at the repository root (the auto-detected root when no
|
|
53
|
+
* `--root` is given). Invalid JSON never crashes the server — it logs a warning
|
|
54
|
+
* and falls back to empty defaults.
|
|
55
|
+
*/
|
|
56
|
+
declare const CONFIG_FILE_NAME = ".tokenshrinkrc.json";
|
|
57
|
+
interface TokenShrinkConfig {
|
|
58
|
+
/** Glob patterns of paths that should never be indexed or watched. */
|
|
59
|
+
ignorePatterns: string[];
|
|
60
|
+
/** Glob patterns of files to index but never prune (full Ring-1 text). */
|
|
61
|
+
keepUnpruned: string[];
|
|
62
|
+
/** Annotation markers (e.g. `@keepContext`) that exempt a definition from pruning. */
|
|
63
|
+
preserveAnnotations: string[];
|
|
64
|
+
/**
|
|
65
|
+
* When false, the generated agent rule carries only lightweight guidance and
|
|
66
|
+
* the model decides when to call the auxiliary tools on its own. Default
|
|
67
|
+
* (true / unset): rules choreograph the tools automatically each task.
|
|
68
|
+
*/
|
|
69
|
+
autoWorkflow?: boolean;
|
|
70
|
+
}
|
|
71
|
+
declare const EMPTY_CONFIG: TokenShrinkConfig;
|
|
72
|
+
declare function configPathFor(root: string): string;
|
|
73
|
+
/** Parse + validate the config at `root`, tolerating any JSON shape. */
|
|
74
|
+
declare function loadConfig(root: string, warn?: (msg: string) => void): TokenShrinkConfig;
|
|
75
|
+
/** True when the (slash-normalized) `file` matches any `pattern`. */
|
|
76
|
+
declare function matchesAny(file: string, patterns: string[]): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Glob matcher with `**`, `*`, `?` and `[...]` support. Patterns that contain
|
|
79
|
+
* no glob metacharacters also match as a path suffix (a bare filename like
|
|
80
|
+
* `global.d.ts` matches any directory containing it).
|
|
81
|
+
*/
|
|
82
|
+
declare function matchesGlob(file: string, pattern: string): boolean;
|
|
83
|
+
/** Compile `**`/`*`/`?`/`[...]` glob into a `/`-normalized regex. */
|
|
84
|
+
declare function globToRegExp(glob: string): RegExp;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Incremental synchronization layer (Phase 3).
|
|
88
|
+
*
|
|
89
|
+
* - Watches the repository with chokidar (ignoring vendor/build dirs).
|
|
90
|
+
* - On add/change, hashes the file and, if the hash changed, re-prunes it and
|
|
91
|
+
* updates the in-memory graph cache.
|
|
92
|
+
* - Extracts import/require specifiers from each file and normalizes relative
|
|
93
|
+
* and aliased paths to absolute file paths on disk.
|
|
94
|
+
*
|
|
95
|
+
* The graph cache is shared with the Context Assembler, which reads ring-1
|
|
96
|
+
* skeletons out of it.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
/** Default paths that will never be indexed or watched. */
|
|
100
|
+
declare const DEFAULT_IGNORED: RegExp[];
|
|
101
|
+
interface CacheEntry {
|
|
102
|
+
/** sha1 of the last-indexed file content. */
|
|
103
|
+
hash: string;
|
|
104
|
+
/** Pruned skeleton for this file. */
|
|
105
|
+
skeleton: string;
|
|
106
|
+
/** The language name used to prune it (or null if unsupported). */
|
|
107
|
+
language: string | null;
|
|
108
|
+
/** Absolute paths of the files this file imports. */
|
|
109
|
+
imports: string[];
|
|
110
|
+
/** Named definitions found while indexing (for expand_symbol / search). */
|
|
111
|
+
symbols?: SymbolInfo[];
|
|
112
|
+
}
|
|
113
|
+
type GraphCache = Map<string, CacheEntry>;
|
|
114
|
+
declare class ContextCache {
|
|
115
|
+
readonly entries: GraphCache;
|
|
116
|
+
private initPromise;
|
|
117
|
+
ensureInit(): Promise<void>;
|
|
118
|
+
/** Returns the cached skeleton for a file, if present. */
|
|
119
|
+
getSkeleton(filePath: string): CacheEntry | null;
|
|
120
|
+
get imports(): GraphCache;
|
|
121
|
+
}
|
|
122
|
+
/** Compute a sha1 of a string. */
|
|
123
|
+
declare function hashOf(text: string): string;
|
|
124
|
+
/**
|
|
125
|
+
* Extract import/require specifiers from source text using a robust,
|
|
126
|
+
* language-agnostic regex (AST-based import queries are grammar-fragile and
|
|
127
|
+
* occasionally malformed; regex covers the common import forms across JS/TS,
|
|
128
|
+
* Python, Go, Rust, Dart, Swift, Java, Kotlin, PHP, C/C++).
|
|
129
|
+
* Returns the matched specifier strings (may be relative or absolute).
|
|
130
|
+
*/
|
|
131
|
+
declare function extractImports(_filePath: string, source: string): string[];
|
|
132
|
+
/** Normalize a specifier to an absolute file path when it resolves locally. */
|
|
133
|
+
declare function resolveImport(importer: string, specifier: string, root: string): string | null;
|
|
134
|
+
interface SyncOptions {
|
|
135
|
+
root: string;
|
|
136
|
+
ignored?: Matcher[];
|
|
137
|
+
/** Optional `.tokenshrinkrc.json` settings. */
|
|
138
|
+
config?: TokenShrinkConfig;
|
|
139
|
+
onIndexed?: (filePath: string, entry: CacheEntry) => void;
|
|
140
|
+
/** Called when a watched file disappears from disk (cache entry dropped). */
|
|
141
|
+
onRemoved?: (filePath: string) => void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Watch a project root and keep the graph cache fresh. Returns the cache and
|
|
145
|
+
* a close() handle. `prune` is awaited per change to keep hot-reload latency
|
|
146
|
+
* predictable.
|
|
147
|
+
*/
|
|
148
|
+
declare function createWatcher(opts: SyncOptions): {
|
|
149
|
+
cache: ContextCache;
|
|
150
|
+
watcher: FSWatcher;
|
|
151
|
+
/** Index an existing file right now (bypasses the watcher). */
|
|
152
|
+
index: (filePath: string) => Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Index the whole tree once (cold start). Returns the number of files
|
|
155
|
+
* successfully indexed.
|
|
156
|
+
*/
|
|
157
|
+
indexAll(): Promise<number>;
|
|
158
|
+
close: () => Promise<void>;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
interface CliOptions {
|
|
162
|
+
port?: number;
|
|
163
|
+
host?: string;
|
|
164
|
+
root?: string;
|
|
165
|
+
ignored?: Matcher[];
|
|
166
|
+
silent?: boolean;
|
|
167
|
+
}
|
|
168
|
+
/** Start the Fastify server; returns the running instance + watcher handle. */
|
|
169
|
+
declare function startServer(opts?: CliOptions): Promise<{
|
|
170
|
+
app: fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault> & PromiseLike<fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>> & {
|
|
171
|
+
__linterBrands: "SafePromiseLike";
|
|
172
|
+
};
|
|
173
|
+
watcher: {
|
|
174
|
+
cache: ContextCache;
|
|
175
|
+
watcher: chokidar.FSWatcher;
|
|
176
|
+
index: (filePath: string) => Promise<void>;
|
|
177
|
+
indexAll(): Promise<number>;
|
|
178
|
+
close: () => Promise<void>;
|
|
179
|
+
};
|
|
180
|
+
}>;
|
|
181
|
+
|
|
182
|
+
export { type CacheEntry as C, DEFAULT_IGNORED as D, EMPTY_CONFIG as E, type GraphCache as G, type SymbolInfo as S, type TokenShrinkConfig as T, type SymbolKind as a, CONFIG_FILE_NAME as b, type CliOptions as c, type SyncOptions as d, collectSymbols as e, configPathFor as f, createWatcher as g, extractImports as h, globToRegExp as i, hashOf as j, matchesAny as k, loadConfig as l, matchSymbols as m, matchesGlob as n, resolveImport as r, startServer as s };
|