token-pilot 0.14.2 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +25 -8
  3. package/dist/ast-index/client.d.ts +2 -89
  4. package/dist/ast-index/client.js +49 -742
  5. package/dist/ast-index/enricher.d.ts +10 -0
  6. package/dist/ast-index/enricher.js +202 -0
  7. package/dist/ast-index/parser.d.ts +31 -0
  8. package/dist/ast-index/parser.js +340 -0
  9. package/dist/ast-index/regex-parser-python.d.ts +8 -0
  10. package/dist/ast-index/regex-parser-python.js +132 -0
  11. package/dist/ast-index/regex-parser.d.ts +8 -0
  12. package/dist/ast-index/regex-parser.js +118 -0
  13. package/dist/config/defaults.js +1 -0
  14. package/dist/core/session-analytics.d.ts +2 -2
  15. package/dist/core/session-analytics.js +78 -61
  16. package/dist/core/symbol-resolver.d.ts +0 -1
  17. package/dist/core/symbol-resolver.js +3 -12
  18. package/dist/core/validation.d.ts +12 -0
  19. package/dist/core/validation.js +62 -2
  20. package/dist/handlers/code-audit.js +2 -2
  21. package/dist/handlers/find-unused.js +1 -1
  22. package/dist/handlers/find-usages.d.ts +1 -1
  23. package/dist/handlers/find-usages.js +93 -25
  24. package/dist/handlers/read-for-edit.d.ts +1 -0
  25. package/dist/handlers/read-for-edit.js +65 -0
  26. package/dist/handlers/read-symbols.d.ts +18 -0
  27. package/dist/handlers/read-symbols.js +142 -0
  28. package/dist/handlers/smart-diff.js +23 -0
  29. package/dist/handlers/smart-read.js +14 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +6 -5
  32. package/dist/server/token-estimates.d.ts +31 -0
  33. package/dist/server/token-estimates.js +204 -0
  34. package/dist/server/tool-definitions.d.ts +1070 -0
  35. package/dist/server/tool-definitions.js +316 -0
  36. package/dist/server.js +23 -480
  37. package/dist/types.d.ts +1 -0
  38. package/package.json +1 -1
  39. package/skills/guide/SKILL.md +64 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,40 @@ All notable changes to Token Pilot will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.16.0] - 2026-03-21
9
+
10
+ ### Added
11
+ - **`read_symbols` tool** — batch read multiple symbols from one file in a single call (max 10). File is read once, AST resolved once. Saves N-1 round-trips vs calling `read_symbol` N times.
12
+ - **`read_for_edit` batch mode** — new `symbols` array parameter reads multiple symbol edit contexts in one call. Each symbol returns raw code ready for Edit tool's `old_string`.
13
+ - **`find_usages` context_lines** — new `context_lines` parameter (0-10) shows surrounding source code for each match. Eliminates follow-up `read_symbol` calls after finding usages.
14
+ - **`smart_diff` affected symbols summary** — consolidated "AFFECTED SYMBOLS" section at the top of diff output, grouped by MODIFIED/ADDED/REMOVED. See all changed functions/classes at a glance.
15
+
16
+ ### Changed
17
+ - **19 tools** (was 18) — added `read_symbols`.
18
+ - **MCP instructions** — added batch read_symbols to decision rules and refactor workflow.
19
+ - **427 tests** (unchanged — all pass with new features).
20
+
21
+ ## [0.15.0] - 2026-03-19
22
+
23
+ ### Added
24
+ - **Regex fallback parser (TS/JS)** — `smart_read` now works for TypeScript/JavaScript files even without ast-index binary. Parses classes, functions, interfaces, types, enums, and class methods via regex. Zero dependencies, 130 lines. Covers ~80% of new users who fail to download ast-index.
25
+ - **Regex fallback parser (Python)** — `smart_read` now works for Python files without ast-index. Parses classes, functions, async functions, decorators (`@dataclass`, `@app.route`), module constants (`UPPER_CASE`), methods with visibility detection (`_private`, `__dunder__`). 150 lines.
26
+ - **Benchmark script** — `scripts/benchmark.ts` measures real token savings on public repos (express, fastify, flask). 92% average savings across 97 files ≥50 lines. Run: `npx tsx scripts/benchmark.ts`.
27
+ - **Guide skill** — `/guide` command shows a quick-reference table of all Token Pilot tools with usage examples and recommended workflow.
28
+ - **`hooks.denyThreshold` config** — hook deny threshold is now configurable in `.token-pilot.json` (default: 300, was hardcoded 500). Intercepts ~2x more native Read calls.
29
+
30
+ ### Changed
31
+ - **Compact session analytics** — `session_analytics` report reduced from ~30 lines to ~5 lines. Shows calls, tokens saved, top 5 tools, top 3 files, cache hit rate on a single screen. Verbose mode (`verbose=true`) restores full breakdown.
32
+ - **`server.ts` refactor** — extracted tool definitions to `server/tool-definitions.ts` and token estimate helpers to `server/token-estimates.ts` (−500 lines from server.ts).
33
+ - **`find_usages` output** — results grouped by file with compact rendering. Single match per file on one line, multiple matches indented under file header.
34
+ - **Stale references** — all `grep_search` hints updated to `Grep` (code-audit, find-unused, find-usages).
35
+ - **README** — benchmark table with real data from 4 public repos. Updated savings claims from 80% to 90% (backed by benchmark).
36
+ - **427 tests** (was 393).
37
+
38
+ ### Fixed
39
+ - **`npx token-pilot` CLI** — symlink path resolution in `isDirectRun` check. All CLI commands now work correctly via npx.
40
+ - **Regex fallback was dead code** — parsers existed but weren't wired into `client.ts` `outline()` method. Now properly called as fallback when ast-index unavailable.
41
+
8
42
  ## [0.14.1] - 2026-03-14
9
43
 
10
44
  ### Fixed
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Token Pilot
2
2
 
3
- MCP server that reduces token consumption in AI coding assistants by **up to 80%** via AST-aware lazy file reading.
3
+ MCP server that reduces token consumption in AI coding assistants by **up to 90%** via AST-aware lazy file reading.
4
4
 
5
5
  Instead of dumping entire files into the LLM context, Token Pilot returns structural overviews (classes, functions, signatures, line ranges) and lets the AI load only the specific symbols it needs.
6
6
 
@@ -13,7 +13,23 @@ Token Pilot: smart_read("user-service.ts") → 15-line outline → ~200 tok
13
13
  After edit: read_diff("user-service.ts") → ~20 tokens
14
14
  ```
15
15
 
16
- **Up to 80% reduction** on large files. Files under 200 lines are returned in full automatically (zero overhead for small files). Typical sessions with a mix of file sizes see **30-50% savings**, scaling higher with repeated reads (session cache, compact reminders) and targeted symbol loading.
16
+ **Up to 90% reduction** on large files. Files under 200 lines are returned in full automatically (zero overhead for small files).
17
+
18
+ ### Benchmarks (real data)
19
+
20
+ Measured on public open-source repos using the regex fallback parser (no ast-index binary). Files ≥50 lines only:
21
+
22
+ | Repo | Files | Raw Tokens | Outline Tokens | Savings |
23
+ |------|------:|----------:|--------------:|--------:|
24
+ | [token-pilot](https://github.com/Digital-Threads/token-pilot) (TS) | 48 | 88,920 | 8,123 | **91%** |
25
+ | [express](https://github.com/expressjs/express) (JS) | 6 | 14,421 | 193 | **99%** |
26
+ | [fastify](https://github.com/fastify/fastify) (JS) | 23 | 50,000 | 3,161 | **94%** |
27
+ | [flask](https://github.com/pallets/flask) (Python) | 20 | 78,236 | 7,418 | **91%** |
28
+ | **Total** | **97** | **231,577** | **18,895** | **92%** |
29
+
30
+ > This measures `smart_read` structural outline savings only. Real sessions also benefit from session cache, dedup reminders, `read_symbol` targeted loading, and `read_for_edit` minimal context.
31
+ >
32
+ > Run the benchmark yourself: `npx tsx scripts/benchmark.ts`
17
33
 
18
34
  ## Installation
19
35
 
@@ -152,15 +168,16 @@ For more control, you can add rules to your project:
152
168
  - **Cursor** → `.cursorrules` in project root
153
169
  - **Codex** → `AGENTS.md` in project root
154
170
 
155
- ## MCP Tools (18)
171
+ ## MCP Tools (19)
156
172
 
157
173
  ### Core Reading
158
174
 
159
175
  | Tool | Instead of | Description |
160
176
  |------|-----------|-------------|
161
- | `smart_read` | `Read` | AST structural overview: classes, functions, methods with signatures. Up to 80% savings on large files. Framework-aware: shows HTTP routes, column types, validation rules. |
177
+ | `smart_read` | `Read` | AST structural overview: classes, functions, methods with signatures. Up to 90% savings on large files. Framework-aware: shows HTTP routes, column types, validation rules. |
162
178
  | `read_symbol` | `Read` + scroll | Load source of a specific symbol. Supports `Class.method`. `show` param: full/head/tail/outline. |
163
- | `read_for_edit` | `Read` before `Edit` | Minimal RAW code around a symbol copy directly as `old_string` for Edit tool. |
179
+ | `read_symbols` | N x `read_symbol` | Batch read multiple symbols from one file in a single call (max 10). One round-trip instead of N. |
180
+ | `read_for_edit` | `Read` before `Edit` | Minimal RAW code around a symbol — copy directly as `old_string` for Edit tool. Batch mode: pass `symbols` array for multiple edit contexts. |
164
181
  | `read_range` | `Read` offset | Read a specific line range from a file. |
165
182
  | `read_diff` | re-`Read` | Show only changed hunks since last smart_read. Requires smart_read before editing (for baseline). Works with any edit tool. |
166
183
  | `smart_read_many` | multiple `Read` | Batch smart_read for up to 20 files in one call. |
@@ -169,14 +186,14 @@ For more control, you can add rules to your project:
169
186
 
170
187
  | Tool | Instead of | Description |
171
188
  |------|-----------|-------------|
172
- | `find_usages` | `Grep` (refs) | All usages of a symbol: definitions, imports, references. Filters: `scope` (path prefix), `kind` (definitions/imports/usages), `lang`, `limit`. |
189
+ | `find_usages` | `Grep` (refs) | All usages of a symbol: definitions, imports, references. Filters: `scope`, `kind`, `lang`, `limit`. Use `context_lines` to include surrounding source code. |
173
190
  | `project_overview` | `ls` + explore | Dual-detection (ast-index + config files) with confidence scoring. Project type, frameworks, quality tools, CI, architecture, directory map. Filter sections with `include`. |
174
191
  | `related_files` | manual explore | Import graph: what a file imports, what imports it, test files. |
175
192
  | `outline` | multiple `smart_read` | Compact overview of all code files in a directory. One call instead of 5-6. Supports `recursive` mode with `max_depth` for deep exploration. |
176
193
  | `find_unused` | manual | Detect dead code — unused functions, classes, variables. |
177
194
  | `code_audit` | multiple `Grep` | Code quality issues in one call: TODO/FIXME comments, deprecated symbols, structural code patterns (via ast-grep), decorator search. |
178
195
  | `module_info` | manual analysis | Module dependency analysis: dependencies, dependents, public API, unused deps. Use for architecture understanding and dependency cleanup. |
179
- | `smart_diff` | raw `git diff` | Structural diff with AST symbol mapping — shows which functions/classes changed instead of raw patch. Scopes: unstaged, staged, commit, branch. |
196
+ | `smart_diff` | raw `git diff` | Structural diff with AST symbol mapping — shows which functions/classes changed instead of raw patch. Affected symbols summary at top. Scopes: unstaged, staged, commit, branch. |
180
197
  | `explore_area` | outline + related_files + git log | One-call directory exploration: structure, imports, tests, recent changes. Replaces 3-5 separate calls. |
181
198
  | `smart_log` | raw `git log` | Structured commit history with category detection (feat/fix/refactor/docs), file stats, author breakdown. Filters by path and ref. |
182
199
  | `test_summary` | raw test output | Run tests and get structured summary: total/passed/failed + failure details. Supports vitest, jest, pytest, phpunit, go, cargo, rspec, mocha. |
@@ -280,7 +297,7 @@ When both are configured, Token Pilot automatically:
280
297
  - Suggests context-mode for large non-code files
281
298
  - Shows combined architecture info in `session_analytics`
282
299
 
283
- **Combined savings: up to 80%** in a typical coding session.
300
+ **Combined savings: up to 90%** in a typical coding session.
284
301
 
285
302
  ## Supported Languages
286
303
 
@@ -20,21 +20,10 @@ export declare class AstIndexClient {
20
20
  init(): Promise<void>;
21
21
  ensureIndex(): Promise<void>;
22
22
  private buildIndex;
23
- /** Mark index as oversized — disables index-dependent tools, outline still works */
24
23
  private handleOversizedIndex;
25
- /** Extract file count from stats output (JSON or text) */
26
- private parseFileCount;
27
24
  outline(filePath: string): Promise<FileStructure | null>;
28
- /**
29
- * Parse text output from `ast-index outline`:
30
- * Outline of src/file.ts:
31
- * :10 ClassName [class]
32
- * :11 propName [property]
33
- * :14 methodName [function]
34
- */
35
- private parseOutlineText;
36
- /** Compute end_line from sequential start positions */
37
- private computeEndLines;
25
+ /** Regex-based fallback for TS/JS/Python when ast-index binary is unavailable. */
26
+ private regexFallback;
38
27
  symbol(name: string): Promise<AstIndexSymbolDetail | null>;
39
28
  search(query: string, options?: {
40
29
  inFile?: string;
@@ -44,119 +33,43 @@ export declare class AstIndexClient {
44
33
  usages(symbolName: string): Promise<AstIndexUsageResult[]>;
45
34
  implementations(name: string): Promise<AstIndexImplementation[]>;
46
35
  hierarchy(name: string): Promise<AstIndexHierarchyNode | null>;
47
- private parseImplementationsText;
48
- private parseHierarchyText;
49
36
  stats(): Promise<string | null>;
50
- /**
51
- * List all files known to the ast-index.
52
- * Parses the `files` command output which lists one file per line.
53
- */
54
37
  listFiles(): Promise<string[]>;
55
- /**
56
- * Cross-references: definitions + imports + usages in one call.
57
- * Replaces separate symbol() + usages() calls.
58
- */
59
38
  refs(symbolName: string, limit?: number): Promise<AstIndexRefsResponse>;
60
- /**
61
- * Project map: directory structure with file counts and symbol kinds.
62
- */
63
39
  map(options?: {
64
40
  module?: string;
65
41
  limit?: number;
66
42
  }): Promise<AstIndexMapResponse | null>;
67
- /**
68
- * Detect project conventions: architecture, frameworks, naming patterns.
69
- */
70
43
  conventions(): Promise<AstIndexConventionsResponse | null>;
71
- /**
72
- * Find callers of a function.
73
- */
74
44
  callers(functionName: string, limit?: number): Promise<AstIndexCallerEntry[]>;
75
- /**
76
- * Show call hierarchy tree (callers tree up).
77
- */
78
45
  callTree(functionName: string, depth?: number): Promise<AstIndexCallTreeNode | null>;
79
- /**
80
- * Show changed symbols since base branch (git diff).
81
- */
82
46
  changed(base?: string): Promise<AstIndexChangedEntry[]>;
83
- /**
84
- * Find potentially unused symbols.
85
- */
86
47
  unusedSymbols(options?: {
87
48
  module?: string;
88
49
  exportOnly?: boolean;
89
50
  limit?: number;
90
51
  }): Promise<AstIndexUnusedSymbol[]>;
91
- /**
92
- * Get imports for a specific file.
93
- * Parses text output: " { X, Y } from 'source';"
94
- */
95
52
  fileImports(filePath: string): Promise<AstIndexImportEntry[]>;
96
- private parseImportsText;
97
- /** Check if ast-grep (sg) is available for structural pattern search */
98
53
  private checkAstGrep;
99
- /** Structural pattern search via ast-grep. Requires ast-grep (sg) installed. */
100
54
  agrep(pattern: string, options?: {
101
55
  lang?: string;
102
56
  limit?: number;
103
57
  }): Promise<AstIndexAgrepMatch[]>;
104
- private parseAgrepText;
105
- /** Find TODO/FIXME/HACK comments in the project */
106
58
  todo(): Promise<AstIndexTodoEntry[]>;
107
- private parseTodoText;
108
- /** Find @Deprecated symbols in the project */
109
59
  deprecated(): Promise<AstIndexDeprecatedEntry[]>;
110
- private parseDeprecatedText;
111
- /** Find symbols with a specific annotation/decorator */
112
60
  annotations(name: string): Promise<AstIndexAnnotationEntry[]>;
113
- private parseAnnotationsText;
114
- /** Trigger incremental index update (called by file watcher after edits) */
115
61
  incrementalUpdate(): Promise<void>;
116
- /** List project modules matching optional pattern */
117
62
  modules(pattern?: string): Promise<AstIndexModuleEntry[]>;
118
- /** Get dependencies of a module */
119
63
  moduleDeps(module: string): Promise<AstIndexModuleDep[]>;
120
- /** Get modules that depend on this module */
121
64
  moduleDependents(module: string): Promise<AstIndexModuleDep[]>;
122
- /** Find unused dependencies of a module */
123
65
  unusedDeps(module: string): Promise<AstIndexUnusedDep[]>;
124
- /** Get public API of a module */
125
66
  moduleApi(module: string): Promise<AstIndexModuleApi[]>;
126
- private parseModuleListText;
127
- private parseModuleDepText;
128
- private parseUnusedDepsText;
129
- private parseModuleApiText;
130
67
  isAvailable(): boolean;
131
- /** Returns true if the index was built but found >50k files (node_modules leak) */
132
68
  isOversized(): boolean;
133
- /** Returns true if index building is disabled (dangerous root like /) */
134
69
  isDisabled(): boolean;
135
- /** Disable index building (e.g. project root is / or home dir) */
136
70
  disableIndex(): void;
137
- /** Re-enable index building after auto-detecting a valid project root */
138
71
  enableIndex(): void;
139
- /** Update project root (e.g. after auto-detecting from file path) */
140
72
  updateProjectRoot(newRoot: string): void;
141
73
  private exec;
142
- private buildFileStructure;
143
- /**
144
- * Python: ast-index doesn't return methods inside classes.
145
- * Parse file content to extract `def` methods for classes without children.
146
- */
147
- private enrichPythonClassMethods;
148
- /**
149
- * PHP: ast-index doesn't return methods inside classes.
150
- * Parse file content to extract `function` methods for classes without children.
151
- */
152
- private enrichPHPClassMethods;
153
- /** Fix the last entry's end_line to use actual file line count */
154
- private fixLastEndLine;
155
- /** Read actual signature lines from file content */
156
- private enrichSignatures;
157
- private mapOutlineEntry;
158
- private mapKind;
159
- private mapVisibility;
160
- private detectLanguage;
161
74
  }
162
75
  //# sourceMappingURL=client.d.ts.map