token-pilot 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +19 -5
- package/dist/config/defaults.js +2 -0
- package/dist/core/policy-engine.d.ts +6 -0
- package/dist/core/policy-engine.js +24 -0
- package/dist/core/validation.d.ts +7 -0
- package/dist/core/validation.js +18 -3
- package/dist/handlers/csv-sections.d.ts +35 -0
- package/dist/handlers/csv-sections.js +129 -0
- package/dist/handlers/json-sections.d.ts +17 -0
- package/dist/handlers/json-sections.js +66 -0
- package/dist/handlers/markdown-sections.d.ts +15 -0
- package/dist/handlers/markdown-sections.js +49 -0
- package/dist/handlers/non-code.js +48 -11
- package/dist/handlers/read-for-edit.d.ts +1 -0
- package/dist/handlers/read-for-edit.js +107 -1
- package/dist/handlers/read-section.d.ts +12 -0
- package/dist/handlers/read-section.js +96 -0
- package/dist/handlers/session-snapshot.d.ts +14 -0
- package/dist/handlers/session-snapshot.js +22 -0
- package/dist/handlers/smart-read-many.d.ts +1 -0
- package/dist/handlers/smart-read-many.js +1 -1
- package/dist/handlers/smart-read.d.ts +1 -0
- package/dist/handlers/smart-read.js +50 -27
- package/dist/handlers/yaml-sections.d.ts +17 -0
- package/dist/handlers/yaml-sections.js +46 -0
- package/dist/server/tool-definitions.d.ts +298 -0
- package/dist/server/tool-definitions.js +40 -0
- package/dist/server.js +34 -1
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -27,14 +27,20 @@ export const MCP_INSTRUCTIONS = [
|
|
|
27
27
|
'15. Code quality → code_audit (TODOs, deprecated, structural patterns)',
|
|
28
28
|
'16. Dead code → find_unused (unreferenced symbols across project)',
|
|
29
29
|
'17. Module architecture → module_info (deps, dependents, public API)',
|
|
30
|
+
'18. Read markdown/yaml/json/csv section → read_section (loads one heading/key/row-range, NOT the whole file)',
|
|
31
|
+
' - For editing sections: read_for_edit(path, section="Section Name")',
|
|
32
|
+
'19. Long session / before compaction → session_snapshot (capture goal, confirmed facts, files, next step as <200 token block)',
|
|
33
|
+
' - Budget-constrained? Use smart_read(max_tokens=N) to auto-downgrade output size',
|
|
30
34
|
'',
|
|
31
35
|
'USE DEFAULT TOOLS ONLY FOR: regex text search → Grep | exact raw content → Read | non-code configs → Read',
|
|
32
36
|
'',
|
|
33
37
|
'WORKFLOWS:',
|
|
34
38
|
'• Explore: project_overview → explore_area → smart_read → read_symbol',
|
|
35
39
|
'• Edit: smart_read → read_symbol(include_edit_context=true) → Edit → read_diff',
|
|
40
|
+
'• Docs: smart_read (outline) → read_section → read_for_edit(section=) → Edit → read_diff',
|
|
36
41
|
'• Refactor: find_usages → read_symbols → read_for_edit → Edit → test_summary',
|
|
37
42
|
'• Audit: code_audit + find_unused + Grep (for regex patterns)',
|
|
43
|
+
'• Long session: session_snapshot → compact context → continue with minimal state',
|
|
38
44
|
].join('\n');
|
|
39
45
|
export const TOOL_DEFINITIONS = [
|
|
40
46
|
// --- Core reading tools ---
|
|
@@ -53,6 +59,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
53
59
|
enum: ['full', 'nav', 'exports'],
|
|
54
60
|
description: 'Output scope: full (default, all details), nav (names + lines only, 2-3x smaller), exports (public API only)',
|
|
55
61
|
},
|
|
62
|
+
max_tokens: { type: 'number', description: 'Token budget. If output exceeds this, auto-downgrades: full → outline → compact. Use for context-constrained sessions.' },
|
|
56
63
|
},
|
|
57
64
|
required: ['path'],
|
|
58
65
|
},
|
|
@@ -108,6 +115,18 @@ export const TOOL_DEFINITIONS = [
|
|
|
108
115
|
required: ['path', 'start_line', 'end_line'],
|
|
109
116
|
},
|
|
110
117
|
},
|
|
118
|
+
{
|
|
119
|
+
name: 'read_section',
|
|
120
|
+
description: 'Read a specific section from Markdown, YAML, JSON, or CSV files. Markdown: by heading name. YAML/JSON: by top-level key. CSV: by row range (rows:1-50). Much cheaper than reading the whole file.',
|
|
121
|
+
inputSchema: {
|
|
122
|
+
type: 'object',
|
|
123
|
+
properties: {
|
|
124
|
+
path: { type: 'string', description: 'Path to .md, .yaml, .yml, .json, or .csv file' },
|
|
125
|
+
heading: { type: 'string', description: 'Section heading (Markdown), top-level key (YAML/JSON), or row range "rows:1-50" (CSV). Case-insensitive.' },
|
|
126
|
+
},
|
|
127
|
+
required: ['path', 'heading'],
|
|
128
|
+
},
|
|
129
|
+
},
|
|
111
130
|
{
|
|
112
131
|
name: 'read_diff',
|
|
113
132
|
description: 'Use INSTEAD OF re-reading whole file after edits. Shows only changed hunks. REQUIRES: call smart_read or read_for_edit BEFORE editing to create baseline snapshot.',
|
|
@@ -138,6 +157,10 @@ export const TOOL_DEFINITIONS = [
|
|
|
138
157
|
include_callers: { type: 'boolean', description: 'Show top callers of this symbol (saves a separate find_usages call)' },
|
|
139
158
|
include_tests: { type: 'boolean', description: 'Show related test file and test names' },
|
|
140
159
|
include_changes: { type: 'boolean', description: 'Show recent git changes in the target region' },
|
|
160
|
+
section: {
|
|
161
|
+
type: 'string',
|
|
162
|
+
description: 'Section to edit: heading (Markdown), top-level key (YAML/JSON), or "rows:1-50" (CSV). Returns raw section content for Edit old_string.',
|
|
163
|
+
},
|
|
141
164
|
},
|
|
142
165
|
required: ['path'],
|
|
143
166
|
},
|
|
@@ -153,6 +176,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
153
176
|
items: { type: 'string' },
|
|
154
177
|
description: 'Array of file paths',
|
|
155
178
|
},
|
|
179
|
+
max_tokens: { type: 'number', description: 'Token budget per file. If a file exceeds this, auto-downgrades to compact outline.' },
|
|
156
180
|
},
|
|
157
181
|
required: ['paths'],
|
|
158
182
|
},
|
|
@@ -330,5 +354,21 @@ export const TOOL_DEFINITIONS = [
|
|
|
330
354
|
required: ['command'],
|
|
331
355
|
},
|
|
332
356
|
},
|
|
357
|
+
// --- Session ---
|
|
358
|
+
{
|
|
359
|
+
name: 'session_snapshot',
|
|
360
|
+
description: 'Capture current session state as a compact markdown block (<200 tokens). Call before compaction, when switching direction, or periodically in long sessions. Model provides the facts, tool formats them.',
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: 'object',
|
|
363
|
+
properties: {
|
|
364
|
+
goal: { type: 'string', description: 'Session goal — what and why' },
|
|
365
|
+
confirmed: { type: 'array', items: { type: 'string' }, description: 'Established facts (what has been verified)' },
|
|
366
|
+
files: { type: 'array', items: { type: 'string' }, description: 'Relevant file paths' },
|
|
367
|
+
blocked: { type: 'string', description: 'Current blocker or obstacle' },
|
|
368
|
+
next: { type: 'string', description: 'Next step to take' },
|
|
369
|
+
},
|
|
370
|
+
required: ['goal'],
|
|
371
|
+
},
|
|
372
|
+
},
|
|
333
373
|
];
|
|
334
374
|
//# sourceMappingURL=tool-definitions.js.map
|
package/dist/server.js
CHANGED
|
@@ -36,12 +36,14 @@ import { handleSmartDiff } from './handlers/smart-diff.js';
|
|
|
36
36
|
import { handleExploreArea } from './handlers/explore-area.js';
|
|
37
37
|
import { handleSmartLog } from './handlers/smart-log.js';
|
|
38
38
|
import { handleTestSummary } from './handlers/test-summary.js';
|
|
39
|
+
import { handleSessionSnapshot } from './handlers/session-snapshot.js';
|
|
40
|
+
import { handleReadSection } from './handlers/read-section.js';
|
|
39
41
|
import { detectContextMode } from './integration/context-mode-detector.js';
|
|
40
42
|
import { estimateTokens } from './core/token-estimator.js';
|
|
41
43
|
import { checkPolicy, isFullReadTool } from './core/policy-engine.js';
|
|
42
44
|
import { MCP_INSTRUCTIONS, TOOL_DEFINITIONS } from './server/tool-definitions.js';
|
|
43
45
|
import { createTokenEstimates } from './server/token-estimates.js';
|
|
44
|
-
import { validateSmartReadArgs, validateReadSymbolArgs, validateReadSymbolsArgs, validateReadRangeArgs, validateReadDiffArgs, validateFindUsagesArgs, validateSmartReadManyArgs, validateReadForEditArgs, validateRelatedFilesArgs, validateOutlineArgs, validateFindUnusedArgs, validateCodeAuditArgs, validateProjectOverviewArgs, validateModuleInfoArgs, validateSmartDiffArgs, validateExploreAreaArgs, validateSmartLogArgs, validateTestSummaryArgs, } from './core/validation.js';
|
|
46
|
+
import { validateSmartReadArgs, validateReadSymbolArgs, validateReadSymbolsArgs, validateReadRangeArgs, validateReadDiffArgs, validateFindUsagesArgs, validateSmartReadManyArgs, validateReadForEditArgs, validateRelatedFilesArgs, validateOutlineArgs, validateFindUnusedArgs, validateCodeAuditArgs, validateProjectOverviewArgs, validateModuleInfoArgs, validateSmartDiffArgs, validateExploreAreaArgs, validateSmartLogArgs, validateTestSummaryArgs, validateReadSectionArgs, } from './core/validation.js';
|
|
45
47
|
export async function createServer(projectRoot, options) {
|
|
46
48
|
const config = await loadConfig(projectRoot);
|
|
47
49
|
const astIndex = new AstIndexClient(projectRoot, config.astIndex.timeout, {
|
|
@@ -153,6 +155,8 @@ export async function createServer(projectRoot, options) {
|
|
|
153
155
|
: null;
|
|
154
156
|
// Policy engine state
|
|
155
157
|
let fullFileReadsCount = 0;
|
|
158
|
+
let totalCallCount = 0;
|
|
159
|
+
let totalTokensReturned = 0;
|
|
156
160
|
const readForEditCalled = new Set();
|
|
157
161
|
// Detect context-mode companion
|
|
158
162
|
const cmEnabled = config.contextMode.enabled;
|
|
@@ -223,6 +227,8 @@ export async function createServer(projectRoot, options) {
|
|
|
223
227
|
}),
|
|
224
228
|
});
|
|
225
229
|
// Policy tracking
|
|
230
|
+
totalCallCount++;
|
|
231
|
+
totalTokensReturned += rest.tokensReturned;
|
|
226
232
|
if (isFullReadTool(rest.tool)) {
|
|
227
233
|
fullFileReadsCount++;
|
|
228
234
|
}
|
|
@@ -234,6 +240,8 @@ export async function createServer(projectRoot, options) {
|
|
|
234
240
|
fullFileReadsCount,
|
|
235
241
|
tokensReturned: rest.tokensReturned,
|
|
236
242
|
readForEditCalled,
|
|
243
|
+
totalCallCount,
|
|
244
|
+
totalTokensReturned,
|
|
237
245
|
});
|
|
238
246
|
return advisory ? `\n${advisory.message}` : null;
|
|
239
247
|
}
|
|
@@ -310,6 +318,20 @@ export async function createServer(projectRoot, options) {
|
|
|
310
318
|
recordWithTrace({ tool: 'read_range', path: rangeArgs.path, tokensReturned: rangeTokens, tokensWouldBe: fullTokensRange || rangeTokens, timestamp: Date.now(), savingsCategory: detectSavingsCategory(rangeText), absPath: resolve(projectRoot, rangeArgs.path), args: rangeArgs });
|
|
311
319
|
return rangeResult;
|
|
312
320
|
}
|
|
321
|
+
case 'read_section': {
|
|
322
|
+
const secArgs = validateReadSectionArgs(args);
|
|
323
|
+
const secResult = await handleReadSection(secArgs, projectRoot, contextRegistry);
|
|
324
|
+
const secText = secResult.content[0]?.text ?? '';
|
|
325
|
+
const secTokens = estimateTokens(secText);
|
|
326
|
+
const fullTokensSec = await fullFileTokens(secArgs.path);
|
|
327
|
+
recordWithTrace({
|
|
328
|
+
tool: 'read_section', path: secArgs.path,
|
|
329
|
+
tokensReturned: secTokens, tokensWouldBe: fullTokensSec || secTokens,
|
|
330
|
+
timestamp: Date.now(), savingsCategory: 'compression',
|
|
331
|
+
absPath: resolve(projectRoot, secArgs.path), args: secArgs,
|
|
332
|
+
});
|
|
333
|
+
return secResult;
|
|
334
|
+
}
|
|
313
335
|
case 'read_diff': {
|
|
314
336
|
const diffArgs = validateReadDiffArgs(args);
|
|
315
337
|
const diffResult = await handleReadDiff(diffArgs, projectRoot, fileCache, contextRegistry);
|
|
@@ -560,6 +582,17 @@ export async function createServer(projectRoot, options) {
|
|
|
560
582
|
recordWithTrace({ tool: 'test_summary', path: tsArgs.command, tokensReturned: tsTokens, tokensWouldBe: tsResult.rawTokens || tsTokens, timestamp: Date.now(), savingsCategory: 'compression', args: tsArgs });
|
|
561
583
|
return { content: tsResult.content };
|
|
562
584
|
}
|
|
585
|
+
case 'session_snapshot': {
|
|
586
|
+
const snapshotArgs = args;
|
|
587
|
+
if (!snapshotArgs.goal) {
|
|
588
|
+
return { content: [{ type: 'text', text: 'Error: goal is required' }], isError: true };
|
|
589
|
+
}
|
|
590
|
+
const snapshotResult = handleSessionSnapshot(snapshotArgs);
|
|
591
|
+
const snapshotText = snapshotResult.content[0]?.text ?? '';
|
|
592
|
+
const snapshotTokens = estimateTokens(snapshotText);
|
|
593
|
+
recordWithTrace({ tool: 'session_snapshot', tokensReturned: snapshotTokens, tokensWouldBe: snapshotTokens, timestamp: Date.now(), savingsCategory: 'compression' });
|
|
594
|
+
return { content: snapshotResult.content };
|
|
595
|
+
}
|
|
563
596
|
default:
|
|
564
597
|
return {
|
|
565
598
|
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "token-pilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Save up to 80% tokens when AI reads code — MCP server for token-efficient code navigation, AST-aware structural reading instead of dumping full files into context window",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|