@ajdev0/token-shrink 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
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';
1
+ import Parser from 'web-tree-sitter';
2
+ import { S as SymbolInfo, C as CacheEntry, a as SymbolKind, G as GraphCache } from './cli-DzY7l7Rr.cjs';
3
+ export { b as CONFIG_FILE_NAME, c as CliOptions, D as DEFAULT_IGNORED, E as EMPTY_CONFIG, d as SyncOptions, T as TokenShrinkConfig, e as collectSymbols, f as configPathFor, g as createWatcher, h as extractImports, i as globToRegExp, j as hashOf, l as loadConfig, m as matchSymbols, k as matchesAny, n as matchesGlob, r as resolveImport, s as startServer } from './cli-DzY7l7Rr.cjs';
3
4
  export { AUTO_RULE_PATH, AUTO_RULE_SENTINEL, CLAUDE_RULE_PATH, CLAUDE_RULE_SENTINEL, CLINE_RULE_PATH, CLINE_RULE_SENTINEL, CURSOR_RULE_PATH, McpServerOptions, RULE_TARGET_PATH, RuleTarget, RuleWriteResult, createAutoRule, createCursorRule, startMcpServer } from './mcp.cjs';
4
5
  import 'chokidar';
5
6
  import 'fastify';
@@ -57,12 +58,13 @@ declare const supportedLanguageIds: LanguageId[];
57
58
  declare const allExtensions: string[];
58
59
 
59
60
  /**
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.
61
+ * Single-parse analysis pass. Produces the pruned skeleton (Ring-1 text) and
62
+ * the per-file symbol index from ONE tree-sitter parse, so the watcher never
63
+ * parses a file twice for pruning and symbol extraction.
63
64
  *
64
- * Range splicing is done bottom-up (descending start offset) so that earlier
65
- * replacements never shift the byte offsets of later ones.
65
+ * The previous `prune()` implementation lived in `parser/pruner.ts`; the
66
+ * parser plumbing (init/language cache) moved here and is re-exported from
67
+ * `pruner.ts` for backwards compatibility.
66
68
  */
67
69
 
68
70
  /** A byte-range that will be replaced by `token`. */
@@ -71,26 +73,64 @@ interface PruneRange {
71
73
  end: number;
72
74
  token: string;
73
75
  }
76
+ /** `Parser.init()` only needs to run once; make concurrent calls share it. */
77
+ declare function ensureParserInit(): Promise<void>;
78
+ /** Load (and cache) a decoded Language object for a language spec. */
79
+ declare function loadLanguage(spec: LanguageSpec, force?: boolean): Promise<Parser.Language>;
74
80
  /**
75
- * Prune the implementation bodies out of `source` (a file at `filePath`).
76
- * If the language has no registered rules, returns the source unchanged.
81
+ * Replace all ranges with their tokens. Ranges are pre-sorted descending by
82
+ * start offset so each splice happens at the tail of the string first,
83
+ * keeping earlier offsets stable.
77
84
  */
78
- declare function prune(filePath: string, source: string, opts?: {
85
+ declare function spliceRanges(source: string, ranges: PruneRange[]): {
86
+ code: string;
87
+ removed: number;
88
+ };
89
+ interface AnalyzeOptions {
79
90
  forceDownload?: boolean;
80
- }): Promise<{
91
+ /**
92
+ * Keep the full source instead of producing a pruned skeleton (used by
93
+ * `keepUnpruned` config rules). Symbols are still collected.
94
+ */
95
+ skipPrune?: boolean;
96
+ /**
97
+ * Byte ranges to exempt from pruning (used by `preserveAnnotations` config
98
+ * rules). Blocks fully inside an exempted region are kept unpruned.
99
+ */
100
+ keepBlocksInside?: {
101
+ start: number;
102
+ end: number;
103
+ }[];
104
+ /**
105
+ * Annotation markers (e.g. `@keepContext`, `@api`). Any definition whose
106
+ * preceding source window contains `@<marker>` is kept fully unpruned.
107
+ */
108
+ preserveAnnotations?: string[];
109
+ }
110
+ interface AnalyzeResult {
111
+ /** Pruned skeleton, or the full source when skipped/unsupported. */
81
112
  code: string;
113
+ /** Friendly language name, or null when unsupported/unavailable. */
82
114
  language: string | null;
115
+ /** Number of bytes removed by pruning. */
83
116
  removed: number;
84
- }>;
117
+ /** Named definitions found in this file. */
118
+ symbols: SymbolInfo[];
119
+ }
85
120
  /**
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.
121
+ * Prune a file's implementation bodies and index its symbols from a single
122
+ * parse. When the grammar cannot be loaded (e.g. first offline run) the file
123
+ * is kept usable and unpruned rather than being dropped from the index.
89
124
  */
90
- declare function spliceRanges(source: string, ranges: PruneRange[]): {
125
+ declare function analyze(filePath: string, source: string, opts?: AnalyzeOptions): Promise<AnalyzeResult>;
126
+ /** Back-compat entry point (same contract as the historical `prune`). */
127
+ declare function prune(filePath: string, source: string, opts?: {
128
+ forceDownload?: boolean;
129
+ }): Promise<{
91
130
  code: string;
131
+ language: string | null;
92
132
  removed: number;
93
- };
133
+ }>;
94
134
 
95
135
  /**
96
136
  * WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar
@@ -113,6 +153,74 @@ declare function getGrammar(spec: LanguageSpec, force?: boolean): Promise<Uint8A
113
153
  */
114
154
  declare function warmGrammars(specs?: LanguageSpec[]): Promise<number>;
115
155
 
156
+ /**
157
+ * Project-root auto-detection for zero-config (no `--root`) mode.
158
+ *
159
+ * The MCP server cannot always know its project at startup: clients spawn
160
+ * stdio servers from directories they choose, and shared/global configs have no
161
+ * project at all. When no explicit root is supplied, these helpers locate the
162
+ * repository by walking up from a known path (the process cwd, or the active
163
+ * file of a tool call) until a VCS directory or a project manifest is found.
164
+ */
165
+ /** VCS dirs mark the true repository boundary — the strongest signal. */
166
+ declare const VCS_MARKER_DIRS: readonly [".git", ".hg", ".svn"];
167
+ /** Manifest files that mark a project boundary when no VCS dir exists. */
168
+ declare const PROJECT_MANIFEST_FILES: readonly ["package.json", "tsconfig.json", "pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "go.mod", "Cargo.toml", "pubspec.yaml", "Package.swift", "pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts", "composer.json", "Gemfile", "mix.exs"];
169
+ /**
170
+ * Find the project root that `fromPath` belongs to, or `null` when none can be
171
+ * determined. `fromPath` may be a file or directory (existing or not).
172
+ *
173
+ * Walk-up rules:
174
+ * - the first ancestor containing a VCS dir (`.git`/`.hg`/`.svn`) wins — it is
175
+ * the true repository boundary, even inside a monorepo sub-package;
176
+ * - otherwise the deepest ancestor containing a project manifest
177
+ * (`package.json`, `pyproject.toml`, `go.mod`, …) is returned;
178
+ * - otherwise `null`, meaning the tree holds no recognizable project markers.
179
+ */
180
+ declare function detectProjectRoot(fromPath: string): string | null;
181
+
182
+ /**
183
+ * In-memory symbol signature index for `search_symbol_signatures`.
184
+ *
185
+ * Zero-dependency alternative to SQLite FTS5: we index only symbol metadata
186
+ * (names + signature lines) produced during the tree-sitter analyze pass, so
187
+ * lookups stay well under a millisecond at repository scale without adding a
188
+ * native module to the dependency tree.
189
+ *
190
+ * The index is kept fresh by the watcher: files are added/removed as chokidar
191
+ * events and the analyze pass run.
192
+ */
193
+
194
+ interface SymbolDoc extends SymbolInfo {
195
+ /** Absolute path of the containing file. */
196
+ filePath: string;
197
+ }
198
+ interface SymbolHit extends SymbolDoc {
199
+ /** Higher is better. */
200
+ score: number;
201
+ /** Human label like `file.ts:12 — fn(a: number): number`. */
202
+ label: string;
203
+ }
204
+ declare class SymbolSearch {
205
+ private docs;
206
+ private byFile;
207
+ private inverted;
208
+ get size(): number;
209
+ /** Replace the docs for one file (or remove when `symbols` is empty). */
210
+ setFile(filePath: string, symbols: SymbolInfo[]): void;
211
+ removeFile(filePath: string): void;
212
+ /** Bulk-load a whole cache (used at attach time and cold lazy builds). */
213
+ loadCache(entries: ReadonlyMap<string, CacheEntry>): void;
214
+ /** Ranked symbol hits for `query`. */
215
+ search(query: string, opts?: {
216
+ maxResults?: number;
217
+ kind?: SymbolKind;
218
+ }): SymbolHit[];
219
+ private score;
220
+ private label;
221
+ private rebuildInverted;
222
+ }
223
+
116
224
  /**
117
225
  * Context Assembler (Phase 4). Produces a Markdown context payload from the
118
226
  * graph cache:
@@ -129,14 +237,33 @@ interface AssembleOptions {
129
237
  includeStats?: boolean;
130
238
  /** Maximum number of ring-1 files to include. */
131
239
  maxSkeletons?: number;
240
+ /**
241
+ * Hard token budget for the whole payload (Ring 0 + Ring 1). When set, Ring 1
242
+ * candidates are ranked by relevance and greedily packed until the budget is
243
+ * exhausted; Ring 0 is always kept in full.
244
+ */
245
+ maxTokens?: number;
132
246
  /** Whether the active file itself should also be pruned (Ring 0 raw by default). */
133
247
  pruneActiveFile?: boolean;
134
248
  }
249
+ /** Token accounting for an assembled payload. */
250
+ interface TokenStats {
251
+ activeTokens: number;
252
+ dependencyTokens: number;
253
+ totalTokens: number;
254
+ /** When `maxTokens` was supplied, the budget that was enforced. */
255
+ budget?: number;
256
+ /** Number of Ring 1 candidates dropped by the token budget. */
257
+ trimmed: number;
258
+ }
135
259
  interface AssembleResult {
136
260
  /** Human-readable Markdown payload for an agent. */
137
261
  markdown: string;
262
+ /** First active file (back-compat; prefer `activeFilePaths`). */
138
263
  activeFilePath: string;
139
- /** Ring-0 full text of the active file. */
264
+ /** Every resolved Ring-0 path, in request order. */
265
+ activeFilePaths: string[];
266
+ /** Ring-0 full text of the active file(s). */
140
267
  activeSource: string;
141
268
  /** Ring-1 entries actually included. */
142
269
  included: {
@@ -145,9 +272,22 @@ interface AssembleResult {
145
272
  }[];
146
273
  /** Paths referenced by imports that could not be resolved to a file. */
147
274
  unresolved: string[];
275
+ /** Approximate token accounting for this payload. */
276
+ tokenStats: TokenStats;
148
277
  }
149
278
  /**
150
- * Build the compressed context for an open file.
279
+ * Build the compressed context for one or more open files.
280
+ * `activeFiles` may be absolute or project-relative. Every listed file is
281
+ * emitted in full as Ring 0; the combined set of their local imports is
282
+ * emitted as pruned Ring-1 skeletons, minus any file already in Ring 0.
283
+ *
284
+ * When `opts.maxTokens` is set, Ring 1 candidates are ranked by a cheap
285
+ * relevance proxy (fan-in → path depth → declaration order) and greedily
286
+ * packed until the budget is exhausted; Ring 0 is always kept in full.
287
+ */
288
+ declare function assembleMany(activeFiles: string[], cache: GraphCache, opts?: AssembleOptions): AssembleResult;
289
+ /**
290
+ * Build the compressed context for a single open file.
151
291
  * `activeFilePath` may be absolute or project-relative.
152
292
  */
153
293
  declare function assemble(activeFilePath: string, cache: GraphCache, opts?: AssembleOptions): AssembleResult;
@@ -166,4 +306,4 @@ declare function approximateTokens(text: string): number;
166
306
 
167
307
  declare const version = "2.0.0";
168
308
 
169
- export { type AssembleOptions, type AssembleResult, GraphCache, type LanguageSpec, type Replacement, allExtensions, approximateTokens, assemble, extractSpecifiers, getGrammar, languageForFile, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
309
+ export { type AnalyzeOptions, type AnalyzeResult, type AssembleOptions, type AssembleResult, CacheEntry, GraphCache, type LanguageSpec, PROJECT_MANIFEST_FILES, type PruneRange, type Replacement, type SymbolDoc, type SymbolHit, SymbolInfo, SymbolKind, SymbolSearch, type TokenStats, VCS_MARKER_DIRS, allExtensions, analyze, approximateTokens, assemble, assembleMany, detectProjectRoot, ensureParserInit, extractSpecifiers, getGrammar, languageForFile, loadLanguage, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
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';
1
+ import Parser from 'web-tree-sitter';
2
+ import { S as SymbolInfo, C as CacheEntry, a as SymbolKind, G as GraphCache } from './cli-DzY7l7Rr.js';
3
+ export { b as CONFIG_FILE_NAME, c as CliOptions, D as DEFAULT_IGNORED, E as EMPTY_CONFIG, d as SyncOptions, T as TokenShrinkConfig, e as collectSymbols, f as configPathFor, g as createWatcher, h as extractImports, i as globToRegExp, j as hashOf, l as loadConfig, m as matchSymbols, k as matchesAny, n as matchesGlob, r as resolveImport, s as startServer } from './cli-DzY7l7Rr.js';
3
4
  export { AUTO_RULE_PATH, AUTO_RULE_SENTINEL, CLAUDE_RULE_PATH, CLAUDE_RULE_SENTINEL, CLINE_RULE_PATH, CLINE_RULE_SENTINEL, CURSOR_RULE_PATH, McpServerOptions, RULE_TARGET_PATH, RuleTarget, RuleWriteResult, createAutoRule, createCursorRule, startMcpServer } from './mcp.js';
4
5
  import 'chokidar';
5
6
  import 'fastify';
@@ -57,12 +58,13 @@ declare const supportedLanguageIds: LanguageId[];
57
58
  declare const allExtensions: string[];
58
59
 
59
60
  /**
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.
61
+ * Single-parse analysis pass. Produces the pruned skeleton (Ring-1 text) and
62
+ * the per-file symbol index from ONE tree-sitter parse, so the watcher never
63
+ * parses a file twice for pruning and symbol extraction.
63
64
  *
64
- * Range splicing is done bottom-up (descending start offset) so that earlier
65
- * replacements never shift the byte offsets of later ones.
65
+ * The previous `prune()` implementation lived in `parser/pruner.ts`; the
66
+ * parser plumbing (init/language cache) moved here and is re-exported from
67
+ * `pruner.ts` for backwards compatibility.
66
68
  */
67
69
 
68
70
  /** A byte-range that will be replaced by `token`. */
@@ -71,26 +73,64 @@ interface PruneRange {
71
73
  end: number;
72
74
  token: string;
73
75
  }
76
+ /** `Parser.init()` only needs to run once; make concurrent calls share it. */
77
+ declare function ensureParserInit(): Promise<void>;
78
+ /** Load (and cache) a decoded Language object for a language spec. */
79
+ declare function loadLanguage(spec: LanguageSpec, force?: boolean): Promise<Parser.Language>;
74
80
  /**
75
- * Prune the implementation bodies out of `source` (a file at `filePath`).
76
- * If the language has no registered rules, returns the source unchanged.
81
+ * Replace all ranges with their tokens. Ranges are pre-sorted descending by
82
+ * start offset so each splice happens at the tail of the string first,
83
+ * keeping earlier offsets stable.
77
84
  */
78
- declare function prune(filePath: string, source: string, opts?: {
85
+ declare function spliceRanges(source: string, ranges: PruneRange[]): {
86
+ code: string;
87
+ removed: number;
88
+ };
89
+ interface AnalyzeOptions {
79
90
  forceDownload?: boolean;
80
- }): Promise<{
91
+ /**
92
+ * Keep the full source instead of producing a pruned skeleton (used by
93
+ * `keepUnpruned` config rules). Symbols are still collected.
94
+ */
95
+ skipPrune?: boolean;
96
+ /**
97
+ * Byte ranges to exempt from pruning (used by `preserveAnnotations` config
98
+ * rules). Blocks fully inside an exempted region are kept unpruned.
99
+ */
100
+ keepBlocksInside?: {
101
+ start: number;
102
+ end: number;
103
+ }[];
104
+ /**
105
+ * Annotation markers (e.g. `@keepContext`, `@api`). Any definition whose
106
+ * preceding source window contains `@<marker>` is kept fully unpruned.
107
+ */
108
+ preserveAnnotations?: string[];
109
+ }
110
+ interface AnalyzeResult {
111
+ /** Pruned skeleton, or the full source when skipped/unsupported. */
81
112
  code: string;
113
+ /** Friendly language name, or null when unsupported/unavailable. */
82
114
  language: string | null;
115
+ /** Number of bytes removed by pruning. */
83
116
  removed: number;
84
- }>;
117
+ /** Named definitions found in this file. */
118
+ symbols: SymbolInfo[];
119
+ }
85
120
  /**
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.
121
+ * Prune a file's implementation bodies and index its symbols from a single
122
+ * parse. When the grammar cannot be loaded (e.g. first offline run) the file
123
+ * is kept usable and unpruned rather than being dropped from the index.
89
124
  */
90
- declare function spliceRanges(source: string, ranges: PruneRange[]): {
125
+ declare function analyze(filePath: string, source: string, opts?: AnalyzeOptions): Promise<AnalyzeResult>;
126
+ /** Back-compat entry point (same contract as the historical `prune`). */
127
+ declare function prune(filePath: string, source: string, opts?: {
128
+ forceDownload?: boolean;
129
+ }): Promise<{
91
130
  code: string;
131
+ language: string | null;
92
132
  removed: number;
93
- };
133
+ }>;
94
134
 
95
135
  /**
96
136
  * WASM grammar acquisition. Lazily downloads a language's `.wasm` grammar
@@ -113,6 +153,74 @@ declare function getGrammar(spec: LanguageSpec, force?: boolean): Promise<Uint8A
113
153
  */
114
154
  declare function warmGrammars(specs?: LanguageSpec[]): Promise<number>;
115
155
 
156
+ /**
157
+ * Project-root auto-detection for zero-config (no `--root`) mode.
158
+ *
159
+ * The MCP server cannot always know its project at startup: clients spawn
160
+ * stdio servers from directories they choose, and shared/global configs have no
161
+ * project at all. When no explicit root is supplied, these helpers locate the
162
+ * repository by walking up from a known path (the process cwd, or the active
163
+ * file of a tool call) until a VCS directory or a project manifest is found.
164
+ */
165
+ /** VCS dirs mark the true repository boundary — the strongest signal. */
166
+ declare const VCS_MARKER_DIRS: readonly [".git", ".hg", ".svn"];
167
+ /** Manifest files that mark a project boundary when no VCS dir exists. */
168
+ declare const PROJECT_MANIFEST_FILES: readonly ["package.json", "tsconfig.json", "pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "go.mod", "Cargo.toml", "pubspec.yaml", "Package.swift", "pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts", "composer.json", "Gemfile", "mix.exs"];
169
+ /**
170
+ * Find the project root that `fromPath` belongs to, or `null` when none can be
171
+ * determined. `fromPath` may be a file or directory (existing or not).
172
+ *
173
+ * Walk-up rules:
174
+ * - the first ancestor containing a VCS dir (`.git`/`.hg`/`.svn`) wins — it is
175
+ * the true repository boundary, even inside a monorepo sub-package;
176
+ * - otherwise the deepest ancestor containing a project manifest
177
+ * (`package.json`, `pyproject.toml`, `go.mod`, …) is returned;
178
+ * - otherwise `null`, meaning the tree holds no recognizable project markers.
179
+ */
180
+ declare function detectProjectRoot(fromPath: string): string | null;
181
+
182
+ /**
183
+ * In-memory symbol signature index for `search_symbol_signatures`.
184
+ *
185
+ * Zero-dependency alternative to SQLite FTS5: we index only symbol metadata
186
+ * (names + signature lines) produced during the tree-sitter analyze pass, so
187
+ * lookups stay well under a millisecond at repository scale without adding a
188
+ * native module to the dependency tree.
189
+ *
190
+ * The index is kept fresh by the watcher: files are added/removed as chokidar
191
+ * events and the analyze pass run.
192
+ */
193
+
194
+ interface SymbolDoc extends SymbolInfo {
195
+ /** Absolute path of the containing file. */
196
+ filePath: string;
197
+ }
198
+ interface SymbolHit extends SymbolDoc {
199
+ /** Higher is better. */
200
+ score: number;
201
+ /** Human label like `file.ts:12 — fn(a: number): number`. */
202
+ label: string;
203
+ }
204
+ declare class SymbolSearch {
205
+ private docs;
206
+ private byFile;
207
+ private inverted;
208
+ get size(): number;
209
+ /** Replace the docs for one file (or remove when `symbols` is empty). */
210
+ setFile(filePath: string, symbols: SymbolInfo[]): void;
211
+ removeFile(filePath: string): void;
212
+ /** Bulk-load a whole cache (used at attach time and cold lazy builds). */
213
+ loadCache(entries: ReadonlyMap<string, CacheEntry>): void;
214
+ /** Ranked symbol hits for `query`. */
215
+ search(query: string, opts?: {
216
+ maxResults?: number;
217
+ kind?: SymbolKind;
218
+ }): SymbolHit[];
219
+ private score;
220
+ private label;
221
+ private rebuildInverted;
222
+ }
223
+
116
224
  /**
117
225
  * Context Assembler (Phase 4). Produces a Markdown context payload from the
118
226
  * graph cache:
@@ -129,14 +237,33 @@ interface AssembleOptions {
129
237
  includeStats?: boolean;
130
238
  /** Maximum number of ring-1 files to include. */
131
239
  maxSkeletons?: number;
240
+ /**
241
+ * Hard token budget for the whole payload (Ring 0 + Ring 1). When set, Ring 1
242
+ * candidates are ranked by relevance and greedily packed until the budget is
243
+ * exhausted; Ring 0 is always kept in full.
244
+ */
245
+ maxTokens?: number;
132
246
  /** Whether the active file itself should also be pruned (Ring 0 raw by default). */
133
247
  pruneActiveFile?: boolean;
134
248
  }
249
+ /** Token accounting for an assembled payload. */
250
+ interface TokenStats {
251
+ activeTokens: number;
252
+ dependencyTokens: number;
253
+ totalTokens: number;
254
+ /** When `maxTokens` was supplied, the budget that was enforced. */
255
+ budget?: number;
256
+ /** Number of Ring 1 candidates dropped by the token budget. */
257
+ trimmed: number;
258
+ }
135
259
  interface AssembleResult {
136
260
  /** Human-readable Markdown payload for an agent. */
137
261
  markdown: string;
262
+ /** First active file (back-compat; prefer `activeFilePaths`). */
138
263
  activeFilePath: string;
139
- /** Ring-0 full text of the active file. */
264
+ /** Every resolved Ring-0 path, in request order. */
265
+ activeFilePaths: string[];
266
+ /** Ring-0 full text of the active file(s). */
140
267
  activeSource: string;
141
268
  /** Ring-1 entries actually included. */
142
269
  included: {
@@ -145,9 +272,22 @@ interface AssembleResult {
145
272
  }[];
146
273
  /** Paths referenced by imports that could not be resolved to a file. */
147
274
  unresolved: string[];
275
+ /** Approximate token accounting for this payload. */
276
+ tokenStats: TokenStats;
148
277
  }
149
278
  /**
150
- * Build the compressed context for an open file.
279
+ * Build the compressed context for one or more open files.
280
+ * `activeFiles` may be absolute or project-relative. Every listed file is
281
+ * emitted in full as Ring 0; the combined set of their local imports is
282
+ * emitted as pruned Ring-1 skeletons, minus any file already in Ring 0.
283
+ *
284
+ * When `opts.maxTokens` is set, Ring 1 candidates are ranked by a cheap
285
+ * relevance proxy (fan-in → path depth → declaration order) and greedily
286
+ * packed until the budget is exhausted; Ring 0 is always kept in full.
287
+ */
288
+ declare function assembleMany(activeFiles: string[], cache: GraphCache, opts?: AssembleOptions): AssembleResult;
289
+ /**
290
+ * Build the compressed context for a single open file.
151
291
  * `activeFilePath` may be absolute or project-relative.
152
292
  */
153
293
  declare function assemble(activeFilePath: string, cache: GraphCache, opts?: AssembleOptions): AssembleResult;
@@ -166,4 +306,4 @@ declare function approximateTokens(text: string): number;
166
306
 
167
307
  declare const version = "2.0.0";
168
308
 
169
- export { type AssembleOptions, type AssembleResult, GraphCache, type LanguageSpec, type Replacement, allExtensions, approximateTokens, assemble, extractSpecifiers, getGrammar, languageForFile, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
309
+ export { type AnalyzeOptions, type AnalyzeResult, type AssembleOptions, type AssembleResult, CacheEntry, GraphCache, type LanguageSpec, PROJECT_MANIFEST_FILES, type PruneRange, type Replacement, type SymbolDoc, type SymbolHit, SymbolInfo, SymbolKind, SymbolSearch, type TokenStats, VCS_MARKER_DIRS, allExtensions, analyze, approximateTokens, assemble, assembleMany, detectProjectRoot, ensureParserInit, extractSpecifiers, getGrammar, languageForFile, loadLanguage, prune, registry, spliceRanges, supportedLanguageIds, version, warmGrammars };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-KN4YKUZM.js";
4
+ } from "./chunk-RI64PBQ5.js";
5
5
  import {
6
6
  AUTO_RULE_PATH,
7
7
  AUTO_RULE_SENTINEL,
@@ -10,25 +10,42 @@ import {
10
10
  CLINE_RULE_PATH,
11
11
  CLINE_RULE_SENTINEL,
12
12
  CURSOR_RULE_PATH,
13
+ PROJECT_MANIFEST_FILES,
13
14
  RULE_TARGET_PATH,
15
+ SymbolSearch,
16
+ VCS_MARKER_DIRS,
14
17
  createAutoRule,
15
18
  createCursorRule,
19
+ detectProjectRoot,
16
20
  startMcpServer
17
- } from "./chunk-HBYIAFR4.js";
21
+ } from "./chunk-RLHEIKPR.js";
18
22
  import {
23
+ CONFIG_FILE_NAME,
19
24
  DEFAULT_IGNORED,
25
+ EMPTY_CONFIG,
26
+ analyze,
20
27
  approximateTokens,
21
28
  assemble,
29
+ assembleMany,
30
+ collectSymbols,
31
+ configPathFor,
22
32
  createWatcher,
33
+ ensureParserInit,
23
34
  extractImports,
24
35
  extractSpecifiers,
25
36
  getGrammar,
37
+ globToRegExp,
26
38
  hashOf,
39
+ loadConfig,
40
+ loadLanguage,
41
+ matchSymbols,
42
+ matchesAny,
43
+ matchesGlob,
27
44
  prune,
28
45
  resolveImport,
29
46
  spliceRanges,
30
47
  warmGrammars
31
- } from "./chunk-HRF3BIOV.js";
48
+ } from "./chunk-FYCLLG7F.js";
32
49
  import {
33
50
  allExtensions,
34
51
  languageForFile,
@@ -45,20 +62,37 @@ export {
45
62
  CLAUDE_RULE_SENTINEL,
46
63
  CLINE_RULE_PATH,
47
64
  CLINE_RULE_SENTINEL,
65
+ CONFIG_FILE_NAME,
48
66
  CURSOR_RULE_PATH,
49
67
  DEFAULT_IGNORED,
68
+ EMPTY_CONFIG,
69
+ PROJECT_MANIFEST_FILES,
50
70
  RULE_TARGET_PATH,
71
+ SymbolSearch,
72
+ VCS_MARKER_DIRS,
51
73
  allExtensions,
74
+ analyze,
52
75
  approximateTokens,
53
76
  assemble,
77
+ assembleMany,
78
+ collectSymbols,
79
+ configPathFor,
54
80
  createAutoRule,
55
81
  createCursorRule,
56
82
  createWatcher,
83
+ detectProjectRoot,
84
+ ensureParserInit,
57
85
  extractImports,
58
86
  extractSpecifiers,
59
87
  getGrammar,
88
+ globToRegExp,
60
89
  hashOf,
61
90
  languageForFile,
91
+ loadConfig,
92
+ loadLanguage,
93
+ matchSymbols,
94
+ matchesAny,
95
+ matchesGlob,
62
96
  prune,
63
97
  registry,
64
98
  resolveImport,
package/dist/index.js.map CHANGED
@@ -1 +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 CLINE_RULE_PATH,\n CLINE_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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CO,IAAM,UAAU;","names":[]}
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, analyze, ensureParserInit, loadLanguage } from './parser/analyze.js';\nexport type { AnalyzeOptions, AnalyzeResult, PruneRange } from './parser/analyze.js';\nexport { collectSymbols, matchSymbols } from './parser/symbols.js';\nexport type { SymbolInfo, SymbolKind } from './parser/symbols.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 { detectProjectRoot, PROJECT_MANIFEST_FILES, VCS_MARKER_DIRS } from './detect.js';\n\nexport { SymbolSearch } from './search/index.js';\nexport type { SymbolDoc, SymbolHit } from './search/index.js';\n\nexport {\n loadConfig,\n matchesAny,\n matchesGlob,\n globToRegExp,\n EMPTY_CONFIG,\n CONFIG_FILE_NAME,\n configPathFor,\n} from './config.js';\nexport type { TokenShrinkConfig } from './config.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, assembleMany, extractSpecifiers, approximateTokens } from './server/assembler.js';\nexport type { AssembleOptions, AssembleResult, TokenStats } 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 CLINE_RULE_PATH,\n CLINE_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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DO,IAAM,UAAU;","names":[]}