token-pilot 0.18.0 → 0.19.1
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 +18 -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 +2 -0
- package/dist/core/validation.js +2 -1
- package/dist/handlers/session-snapshot.d.ts +15 -0
- package/dist/handlers/session-snapshot.js +28 -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/server/tool-definitions.d.ts +229 -0
- package/dist/server/tool-definitions.js +22 -0
- package/dist/server.js +18 -0
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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.19.1] - 2026-04-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`decisions` field in `session_snapshot`** — stores key decisions with reasoning (e.g., "removed sysfee step — caused double counting"). Prevents the model from revisiting rejected approaches after context compaction.
|
|
12
|
+
|
|
13
|
+
## [0.19.0] - 2026-04-15
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **`session_snapshot` tool** — capture current session state (goal, confirmed facts, files, blockers, next step) as a compact markdown block (<200 tokens). Call before context compaction or when switching direction in long sessions.
|
|
17
|
+
- **`max_tokens` parameter** on `smart_read` and `smart_read_many` — token budget per read. Output auto-downgrades through three levels: full content → structural outline → compact (symbol names + line ranges only). Enables context-constrained sessions.
|
|
18
|
+
- **Session compaction advisory** — policy engine now tracks total tool calls and tokens returned. Advises calling `session_snapshot()` when thresholds are reached (default: every 15 calls or after 8,000 tokens). Configurable via `compactionCallThreshold` and `compactionTokenThreshold`.
|
|
19
|
+
- **"Why This Approach Works"** section in README explaining the 3-level optimization strategy.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **21 tools** (was 20) — added `session_snapshot`.
|
|
23
|
+
- **MCP instructions** updated with `session_snapshot` workflow and `max_tokens` guidance.
|
|
24
|
+
- Benchmark numbers updated: 55 files, 102K raw → 9K outline tokens (91% savings).
|
|
25
|
+
|
|
8
26
|
## [0.18.0] - 2026-04-05
|
|
9
27
|
|
|
10
28
|
### Added
|
package/README.md
CHANGED
|
@@ -21,16 +21,28 @@ Measured on public open-source repos using the regex fallback parser (no ast-ind
|
|
|
21
21
|
|
|
22
22
|
| Repo | Files | Raw Tokens | Outline Tokens | Savings |
|
|
23
23
|
|------|------:|----------:|--------------:|--------:|
|
|
24
|
-
| [token-pilot](https://github.com/Digital-Threads/token-pilot) (TS) |
|
|
24
|
+
| [token-pilot](https://github.com/Digital-Threads/token-pilot) (TS) | 55 | 102,086 | 8,992 | **91%** |
|
|
25
25
|
| [express](https://github.com/expressjs/express) (JS) | 6 | 14,421 | 193 | **99%** |
|
|
26
26
|
| [fastify](https://github.com/fastify/fastify) (JS) | 23 | 50,000 | 3,161 | **94%** |
|
|
27
27
|
| [flask](https://github.com/pallets/flask) (Python) | 20 | 78,236 | 7,418 | **91%** |
|
|
28
|
-
| **Total** | **
|
|
28
|
+
| **Total** | **104** | **244,743** | **19,764** | **92%** |
|
|
29
29
|
|
|
30
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
31
|
>
|
|
32
32
|
> Run the benchmark yourself: `npx tsx scripts/benchmark.ts`
|
|
33
33
|
|
|
34
|
+
## Why This Approach Works
|
|
35
|
+
|
|
36
|
+
The biggest source of token waste in AI coding sessions isn't verbose prompts — it's **redundant context**. Every time a model re-reads a file, re-sends conversation history, or loads code it doesn't need, you pay for tokens that add no value.
|
|
37
|
+
|
|
38
|
+
Token Pilot attacks this at three levels:
|
|
39
|
+
|
|
40
|
+
1. **Symbol-first reading** — load outlines instead of full files, drill into specific functions on demand. This alone saves 60-90% on most reads.
|
|
41
|
+
2. **Context budget control** — `max_tokens` parameter on `smart_read` auto-downgrades output (full → outline → compact) to fit within a token budget per step.
|
|
42
|
+
3. **Session state management** — `session_snapshot` captures session state as a compact markdown block (<200 tokens), enabling clean context compaction without losing track of what you're doing.
|
|
43
|
+
|
|
44
|
+
These aren't theoretical gains. In real sessions, the combination of structural reading + targeted symbol access + session snapshots consistently reduces token usage by 80-90% compared to raw file reads.
|
|
45
|
+
|
|
34
46
|
## Installation
|
|
35
47
|
|
|
36
48
|
### Quick Start (recommended)
|
|
@@ -152,6 +164,7 @@ WHEN TO USE TOKEN PILOT (saves up to 80% tokens):
|
|
|
152
164
|
• Reading code files → smart_read (returns structure, not raw content)
|
|
153
165
|
• Need one function/class → read_symbol (loads only that symbol)
|
|
154
166
|
• Exploring a directory → outline (all symbols in one call)
|
|
167
|
+
• Long session? → session_snapshot (capture state before compaction)
|
|
155
168
|
...
|
|
156
169
|
WHEN TO USE DEFAULT TOOLS (Token Pilot adds no value):
|
|
157
170
|
• Regex/pattern search → use Grep/ripgrep, NOT find_usages
|
|
@@ -168,13 +181,13 @@ For more control, you can add rules to your project:
|
|
|
168
181
|
- **Cursor** → `.cursorrules` in project root
|
|
169
182
|
- **Codex** → `AGENTS.md` in project root
|
|
170
183
|
|
|
171
|
-
## MCP Tools (
|
|
184
|
+
## MCP Tools (21)
|
|
172
185
|
|
|
173
186
|
### Core Reading
|
|
174
187
|
|
|
175
188
|
| Tool | Instead of | Description |
|
|
176
189
|
|------|-----------|-------------|
|
|
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. |
|
|
190
|
+
| `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. `max_tokens` param for budget-constrained sessions. |
|
|
178
191
|
| `read_symbol` | `Read` + scroll | Load source of a specific symbol. Supports `Class.method`. `show` param: full/head/tail/outline. |
|
|
179
192
|
| `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
193
|
| `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. |
|
|
@@ -198,10 +211,11 @@ For more control, you can add rules to your project:
|
|
|
198
211
|
| `smart_log` | raw `git log` | Structured commit history with category detection (feat/fix/refactor/docs), file stats, author breakdown. Filters by path and ref. |
|
|
199
212
|
| `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. |
|
|
200
213
|
|
|
201
|
-
### Analytics
|
|
214
|
+
### Session & Analytics
|
|
202
215
|
|
|
203
216
|
| Tool | Description |
|
|
204
217
|
|------|-------------|
|
|
218
|
+
| `session_snapshot` | Capture session state as a compact markdown block (<200 tokens): goal, decisions (with reasoning), confirmed facts, relevant files, blockers, next step. Decisions field prevents revisiting rejected approaches after compaction. |
|
|
205
219
|
| `session_analytics` | Token savings report: total saved, per-tool breakdown, top files, per-intent breakdown, decision insights, policy advisories. |
|
|
206
220
|
|
|
207
221
|
## CLI Commands
|
package/dist/config/defaults.js
CHANGED
|
@@ -16,6 +16,10 @@ export interface PolicyConfig {
|
|
|
16
16
|
warnOnLargeReads: boolean;
|
|
17
17
|
/** Token threshold for large read warning */
|
|
18
18
|
largeReadThreshold: number;
|
|
19
|
+
/** Suggest compaction after N total tool calls (0 = disabled) */
|
|
20
|
+
compactionCallThreshold: number;
|
|
21
|
+
/** Suggest compaction after N total tokens returned (0 = disabled) */
|
|
22
|
+
compactionTokenThreshold: number;
|
|
19
23
|
}
|
|
20
24
|
export declare const DEFAULT_POLICIES: PolicyConfig;
|
|
21
25
|
export interface PolicyCheckContext {
|
|
@@ -23,6 +27,8 @@ export interface PolicyCheckContext {
|
|
|
23
27
|
tokensReturned: number;
|
|
24
28
|
readForEditCalled?: Set<string>;
|
|
25
29
|
editTargetPath?: string;
|
|
30
|
+
totalCallCount?: number;
|
|
31
|
+
totalTokensReturned?: number;
|
|
26
32
|
}
|
|
27
33
|
export interface PolicyAdvisory {
|
|
28
34
|
level: 'info' | 'warn';
|
|
@@ -10,6 +10,8 @@ export const DEFAULT_POLICIES = {
|
|
|
10
10
|
maxFullFileReads: 10,
|
|
11
11
|
warnOnLargeReads: true,
|
|
12
12
|
largeReadThreshold: 2000,
|
|
13
|
+
compactionCallThreshold: 15,
|
|
14
|
+
compactionTokenThreshold: 8000,
|
|
13
15
|
};
|
|
14
16
|
/** Full-file read tools that count toward maxFullFileReads */
|
|
15
17
|
const FULL_READ_TOOLS = new Set([
|
|
@@ -64,6 +66,28 @@ export function checkPolicy(policy, tool, context) {
|
|
|
64
66
|
message: `POLICY: Consider using read_for_edit("${context.editTargetPath}") before editing to get precise edit context.`,
|
|
65
67
|
};
|
|
66
68
|
}
|
|
69
|
+
// 5. Session compaction advisory — by call count
|
|
70
|
+
if (policy.compactionCallThreshold > 0 &&
|
|
71
|
+
context.totalCallCount !== undefined &&
|
|
72
|
+
context.totalCallCount > 0 &&
|
|
73
|
+
context.totalCallCount % policy.compactionCallThreshold === 0) {
|
|
74
|
+
return {
|
|
75
|
+
level: 'info',
|
|
76
|
+
message: `COMPACTION: ${context.totalCallCount} tool calls this session. Consider calling session_snapshot() to capture state, then compact context.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// 6. Session compaction advisory — by total tokens
|
|
80
|
+
if (policy.compactionTokenThreshold > 0 &&
|
|
81
|
+
context.totalTokensReturned !== undefined &&
|
|
82
|
+
context.totalTokensReturned > policy.compactionTokenThreshold &&
|
|
83
|
+
context.totalCallCount !== undefined &&
|
|
84
|
+
context.totalCallCount % 5 === 0 // don't spam every call, check every 5th
|
|
85
|
+
) {
|
|
86
|
+
return {
|
|
87
|
+
level: 'info',
|
|
88
|
+
message: `COMPACTION: ~${context.totalTokensReturned} tokens returned this session. Consider calling session_snapshot() to capture state, then compact context.`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
67
91
|
return null;
|
|
68
92
|
}
|
|
69
93
|
/**
|
|
@@ -12,6 +12,7 @@ export declare function validateSmartReadArgs(args: unknown): {
|
|
|
12
12
|
show_docs?: boolean;
|
|
13
13
|
show_references?: boolean;
|
|
14
14
|
depth?: number;
|
|
15
|
+
max_tokens?: number;
|
|
15
16
|
};
|
|
16
17
|
/**
|
|
17
18
|
* Validate read_symbol arguments.
|
|
@@ -67,6 +68,7 @@ export declare function validateFindUsagesArgs(args: unknown): FindUsagesArgs;
|
|
|
67
68
|
*/
|
|
68
69
|
export declare function validateSmartReadManyArgs(args: unknown): {
|
|
69
70
|
paths: string[];
|
|
71
|
+
max_tokens?: number;
|
|
70
72
|
};
|
|
71
73
|
/**
|
|
72
74
|
* Validate read_for_edit arguments.
|
package/dist/core/validation.js
CHANGED
|
@@ -28,6 +28,7 @@ export function validateSmartReadArgs(args) {
|
|
|
28
28
|
show_docs: optionalBool(a.show_docs, 'show_docs'),
|
|
29
29
|
show_references: optionalBool(a.show_references, 'show_references'),
|
|
30
30
|
depth: optionalNumber(a.depth, 'depth'),
|
|
31
|
+
max_tokens: optionalNumber(a.max_tokens, 'max_tokens'),
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
34
|
/**
|
|
@@ -194,7 +195,7 @@ export function validateSmartReadManyArgs(args) {
|
|
|
194
195
|
throw new Error('Each path in "paths" must be a non-empty string.');
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
|
-
return { paths: a.paths };
|
|
198
|
+
return { paths: a.paths, max_tokens: optionalNumber(a.max_tokens, 'max_tokens') };
|
|
198
199
|
}
|
|
199
200
|
function optionalString(val, name) {
|
|
200
201
|
if (val === undefined || val === null)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SessionSnapshotArgs {
|
|
2
|
+
goal: string;
|
|
3
|
+
decisions?: string[];
|
|
4
|
+
confirmed?: string[];
|
|
5
|
+
files?: string[];
|
|
6
|
+
blocked?: string;
|
|
7
|
+
next?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleSessionSnapshot(args: SessionSnapshotArgs): {
|
|
10
|
+
content: {
|
|
11
|
+
type: 'text';
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=session-snapshot.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function handleSessionSnapshot(args) {
|
|
2
|
+
const lines = ['## Session State'];
|
|
3
|
+
lines.push(`**Goal:** ${args.goal}`);
|
|
4
|
+
if (args.decisions?.length) {
|
|
5
|
+
lines.push('**Decisions:**');
|
|
6
|
+
for (const item of args.decisions) {
|
|
7
|
+
lines.push(`- ${item}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
if (args.confirmed?.length) {
|
|
11
|
+
lines.push('**Confirmed:**');
|
|
12
|
+
for (const item of args.confirmed) {
|
|
13
|
+
lines.push(`- ${item}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (args.files?.length) {
|
|
17
|
+
lines.push(`**Files:** ${args.files.join(', ')}`);
|
|
18
|
+
}
|
|
19
|
+
if (args.blocked) {
|
|
20
|
+
lines.push(`**Blocked:** ${args.blocked}`);
|
|
21
|
+
}
|
|
22
|
+
if (args.next) {
|
|
23
|
+
lines.push(`**Next:** ${args.next}`);
|
|
24
|
+
}
|
|
25
|
+
const text = lines.join('\n');
|
|
26
|
+
return { content: [{ type: 'text', text }] };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=session-snapshot.js.map
|
|
@@ -4,6 +4,7 @@ import type { ContextRegistry } from '../core/context-registry.js';
|
|
|
4
4
|
import type { TokenPilotConfig } from '../types.js';
|
|
5
5
|
export interface SmartReadManyArgs {
|
|
6
6
|
paths: string[];
|
|
7
|
+
max_tokens?: number;
|
|
7
8
|
}
|
|
8
9
|
export declare function handleSmartReadMany(args: SmartReadManyArgs, projectRoot: string, astIndex: AstIndexClient, fileCache: FileCache, contextRegistry: ContextRegistry, config: TokenPilotConfig): Promise<{
|
|
9
10
|
content: Array<{
|
|
@@ -32,7 +32,7 @@ export async function handleSmartReadMany(args, projectRoot, astIndex, fileCache
|
|
|
32
32
|
const fullTokens = await estimateFullFileTokens(projectRoot, path);
|
|
33
33
|
return { path, text: reminderText + `\nFor full re-read: smart_read("${path}")`, fullTokens };
|
|
34
34
|
}
|
|
35
|
-
const result = await handleSmartRead({ path }, projectRoot, astIndex, fileCache, contextRegistry, config);
|
|
35
|
+
const result = await handleSmartRead({ path, max_tokens: args.max_tokens }, projectRoot, astIndex, fileCache, contextRegistry, config);
|
|
36
36
|
const text = result.content[0]?.text ?? '';
|
|
37
37
|
const fullTokens = await estimateFullFileTokens(projectRoot, path);
|
|
38
38
|
return { path, text, fullTokens };
|
|
@@ -9,6 +9,7 @@ export interface SmartReadArgs {
|
|
|
9
9
|
show_references?: boolean;
|
|
10
10
|
depth?: number;
|
|
11
11
|
scope?: 'full' | 'nav' | 'exports';
|
|
12
|
+
max_tokens?: number;
|
|
12
13
|
}
|
|
13
14
|
export declare function handleSmartRead(args: SmartReadArgs, projectRoot: string, astIndex: AstIndexClient, fileCache: FileCache, contextRegistry: ContextRegistry, config: TokenPilotConfig): Promise<{
|
|
14
15
|
content: Array<{
|
|
@@ -28,31 +28,35 @@ export async function handleSmartRead(args, projectRoot, astIndex, fileCache, co
|
|
|
28
28
|
if (lines.length <= config.smartRead.smallFileThreshold) {
|
|
29
29
|
const hash = createHash('sha256').update(content).digest('hex');
|
|
30
30
|
const tokens = estimateTokens(content);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Cache for read_diff baseline (so read_diff works after external edits)
|
|
39
|
-
if (!fileCache.get(absPath)) {
|
|
40
|
-
const fileStat = await stat(absPath);
|
|
41
|
-
fileCache.set(absPath, {
|
|
42
|
-
structure: {
|
|
43
|
-
path: absPath, language: 'unknown',
|
|
44
|
-
meta: { lines: lines.length, bytes: content.length, lastModified: fileStat.mtimeMs, contentHash: hash },
|
|
45
|
-
imports: [], exports: [], symbols: [],
|
|
46
|
-
},
|
|
47
|
-
content, lines, mtime: fileStat.mtimeMs, hash, lastAccess: Date.now(),
|
|
31
|
+
// Budget check: if full content exceeds max_tokens, skip pass-through and use outline path
|
|
32
|
+
if (!args.max_tokens || tokens <= args.max_tokens) {
|
|
33
|
+
contextRegistry.trackLoad(absPath, {
|
|
34
|
+
type: 'full',
|
|
35
|
+
startLine: 1,
|
|
36
|
+
endLine: lines.length,
|
|
37
|
+
tokens,
|
|
48
38
|
});
|
|
39
|
+
contextRegistry.setContentHash(absPath, hash);
|
|
40
|
+
// Cache for read_diff baseline (so read_diff works after external edits)
|
|
41
|
+
if (!fileCache.get(absPath)) {
|
|
42
|
+
const fileStat = await stat(absPath);
|
|
43
|
+
fileCache.set(absPath, {
|
|
44
|
+
structure: {
|
|
45
|
+
path: absPath, language: 'unknown',
|
|
46
|
+
meta: { lines: lines.length, bytes: content.length, lastModified: fileStat.mtimeMs, contentHash: hash },
|
|
47
|
+
imports: [], exports: [], symbols: [],
|
|
48
|
+
},
|
|
49
|
+
content, lines, mtime: fileStat.mtimeMs, hash, lastAccess: Date.now(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
content: [{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: `FILE: ${args.path} (${lines.length} lines — returned in full, below threshold)\n\n${content}`,
|
|
56
|
+
}],
|
|
57
|
+
};
|
|
49
58
|
}
|
|
50
|
-
|
|
51
|
-
content: [{
|
|
52
|
-
type: 'text',
|
|
53
|
-
text: `FILE: ${args.path} (${lines.length} lines — returned in full, below threshold)\n\n${content}`,
|
|
54
|
-
}],
|
|
55
|
-
};
|
|
59
|
+
// else: fall through to outline path even for small files
|
|
56
60
|
}
|
|
57
61
|
// 3. Check cache
|
|
58
62
|
let cached = fileCache.get(absPath);
|
|
@@ -174,7 +178,7 @@ export async function handleSmartRead(args, projectRoot, astIndex, fileCache, co
|
|
|
174
178
|
// 6b. Adaptive fallback: if outline is not significantly smaller than raw, return raw
|
|
175
179
|
const structureTokens = estimateTokens(output);
|
|
176
180
|
const fullTokens = estimateTokens(content);
|
|
177
|
-
if (structureTokens >= fullTokens * 0.7) {
|
|
181
|
+
if (structureTokens >= fullTokens * 0.7 && (!args.max_tokens || fullTokens <= args.max_tokens)) {
|
|
178
182
|
contextRegistry.trackLoad(absPath, {
|
|
179
183
|
type: 'full',
|
|
180
184
|
startLine: 1,
|
|
@@ -192,11 +196,30 @@ export async function handleSmartRead(args, projectRoot, astIndex, fileCache, co
|
|
|
192
196
|
}],
|
|
193
197
|
};
|
|
194
198
|
}
|
|
195
|
-
// 7.
|
|
199
|
+
// 7. Budget enforcement: if outline exceeds max_tokens, return compact version
|
|
200
|
+
if (args.max_tokens && structureTokens > args.max_tokens) {
|
|
201
|
+
const symbols = cached.structure.symbols;
|
|
202
|
+
const compactLines = [
|
|
203
|
+
`FILE: ${args.path} (${lines.length} lines — compact, budget: ${args.max_tokens} tokens)`,
|
|
204
|
+
`Imports: ${cached.structure.imports?.length ?? 0} | Exports: ${cached.structure.exports?.length ?? 0} | Symbols: ${symbols.length}`,
|
|
205
|
+
'',
|
|
206
|
+
];
|
|
207
|
+
for (const sym of symbols) {
|
|
208
|
+
compactLines.push(` ${sym.kind} ${sym.name} [L${sym.location.startLine}-${sym.location.endLine}]`);
|
|
209
|
+
}
|
|
210
|
+
compactLines.push('', `Use read_symbol("${args.path}", "<name>") to drill into any symbol.`);
|
|
211
|
+
const compactText = compactLines.join('\n');
|
|
212
|
+
const compactTokens = estimateTokens(compactText);
|
|
213
|
+
contextRegistry.trackLoad(absPath, { type: 'structure', startLine: 1, endLine: cached.structure.meta.lines, tokens: compactTokens });
|
|
214
|
+
contextRegistry.setContentHash(absPath, cached.hash);
|
|
215
|
+
contextRegistry.trackStructureSymbols(absPath, symbols.map(s => s.name));
|
|
216
|
+
return { content: [{ type: 'text', text: compactText }] };
|
|
217
|
+
}
|
|
218
|
+
// 8. Add token savings
|
|
196
219
|
const savings = config.display.showTokenSavings
|
|
197
220
|
? '\n' + formatSavings(structureTokens, fullTokens)
|
|
198
221
|
: '';
|
|
199
|
-
//
|
|
222
|
+
// 9. Track
|
|
200
223
|
contextRegistry.trackLoad(absPath, {
|
|
201
224
|
type: 'structure',
|
|
202
225
|
startLine: 1,
|
|
@@ -205,7 +228,7 @@ export async function handleSmartRead(args, projectRoot, astIndex, fileCache, co
|
|
|
205
228
|
});
|
|
206
229
|
contextRegistry.setContentHash(absPath, cached.hash);
|
|
207
230
|
contextRegistry.trackStructureSymbols(absPath, cached.structure.symbols.map(s => s.name));
|
|
208
|
-
//
|
|
231
|
+
// 10. Confidence metadata
|
|
209
232
|
const confidenceMeta = assessConfidence({
|
|
210
233
|
symbolResolved: (cached.structure.symbols?.length ?? 0) > 0,
|
|
211
234
|
fullFile: false,
|
|
@@ -30,6 +30,10 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
30
30
|
enum: string[];
|
|
31
31
|
description: string;
|
|
32
32
|
};
|
|
33
|
+
max_tokens: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
33
37
|
symbol?: undefined;
|
|
34
38
|
context_before?: undefined;
|
|
35
39
|
context_after?: undefined;
|
|
@@ -65,6 +69,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
65
69
|
command?: undefined;
|
|
66
70
|
runner?: undefined;
|
|
67
71
|
timeout?: undefined;
|
|
72
|
+
goal?: undefined;
|
|
73
|
+
decisions?: undefined;
|
|
74
|
+
confirmed?: undefined;
|
|
75
|
+
files?: undefined;
|
|
76
|
+
blocked?: undefined;
|
|
77
|
+
next?: undefined;
|
|
68
78
|
};
|
|
69
79
|
required: string[];
|
|
70
80
|
};
|
|
@@ -103,6 +113,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
103
113
|
show_docs?: undefined;
|
|
104
114
|
depth?: undefined;
|
|
105
115
|
scope?: undefined;
|
|
116
|
+
max_tokens?: undefined;
|
|
106
117
|
symbols?: undefined;
|
|
107
118
|
start_line?: undefined;
|
|
108
119
|
end_line?: undefined;
|
|
@@ -133,6 +144,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
133
144
|
command?: undefined;
|
|
134
145
|
runner?: undefined;
|
|
135
146
|
timeout?: undefined;
|
|
147
|
+
goal?: undefined;
|
|
148
|
+
decisions?: undefined;
|
|
149
|
+
confirmed?: undefined;
|
|
150
|
+
files?: undefined;
|
|
151
|
+
blocked?: undefined;
|
|
152
|
+
next?: undefined;
|
|
136
153
|
};
|
|
137
154
|
required: string[];
|
|
138
155
|
};
|
|
@@ -170,6 +187,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
170
187
|
show_docs?: undefined;
|
|
171
188
|
depth?: undefined;
|
|
172
189
|
scope?: undefined;
|
|
190
|
+
max_tokens?: undefined;
|
|
173
191
|
symbol?: undefined;
|
|
174
192
|
include_edit_context?: undefined;
|
|
175
193
|
start_line?: undefined;
|
|
@@ -201,6 +219,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
201
219
|
command?: undefined;
|
|
202
220
|
runner?: undefined;
|
|
203
221
|
timeout?: undefined;
|
|
222
|
+
goal?: undefined;
|
|
223
|
+
decisions?: undefined;
|
|
224
|
+
confirmed?: undefined;
|
|
225
|
+
files?: undefined;
|
|
226
|
+
blocked?: undefined;
|
|
227
|
+
next?: undefined;
|
|
204
228
|
};
|
|
205
229
|
required: string[];
|
|
206
230
|
};
|
|
@@ -226,6 +250,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
226
250
|
show_docs?: undefined;
|
|
227
251
|
depth?: undefined;
|
|
228
252
|
scope?: undefined;
|
|
253
|
+
max_tokens?: undefined;
|
|
229
254
|
symbol?: undefined;
|
|
230
255
|
context_before?: undefined;
|
|
231
256
|
context_after?: undefined;
|
|
@@ -259,6 +284,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
259
284
|
command?: undefined;
|
|
260
285
|
runner?: undefined;
|
|
261
286
|
timeout?: undefined;
|
|
287
|
+
goal?: undefined;
|
|
288
|
+
decisions?: undefined;
|
|
289
|
+
confirmed?: undefined;
|
|
290
|
+
files?: undefined;
|
|
291
|
+
blocked?: undefined;
|
|
292
|
+
next?: undefined;
|
|
262
293
|
};
|
|
263
294
|
required: string[];
|
|
264
295
|
};
|
|
@@ -280,6 +311,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
280
311
|
show_docs?: undefined;
|
|
281
312
|
depth?: undefined;
|
|
282
313
|
scope?: undefined;
|
|
314
|
+
max_tokens?: undefined;
|
|
283
315
|
symbol?: undefined;
|
|
284
316
|
context_before?: undefined;
|
|
285
317
|
context_after?: undefined;
|
|
@@ -314,6 +346,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
314
346
|
command?: undefined;
|
|
315
347
|
runner?: undefined;
|
|
316
348
|
timeout?: undefined;
|
|
349
|
+
goal?: undefined;
|
|
350
|
+
decisions?: undefined;
|
|
351
|
+
confirmed?: undefined;
|
|
352
|
+
files?: undefined;
|
|
353
|
+
blocked?: undefined;
|
|
354
|
+
next?: undefined;
|
|
317
355
|
};
|
|
318
356
|
required: string[];
|
|
319
357
|
};
|
|
@@ -335,6 +373,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
335
373
|
show_docs?: undefined;
|
|
336
374
|
depth?: undefined;
|
|
337
375
|
scope?: undefined;
|
|
376
|
+
max_tokens?: undefined;
|
|
338
377
|
symbol?: undefined;
|
|
339
378
|
context_before?: undefined;
|
|
340
379
|
context_after?: undefined;
|
|
@@ -369,6 +408,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
369
408
|
command?: undefined;
|
|
370
409
|
runner?: undefined;
|
|
371
410
|
timeout?: undefined;
|
|
411
|
+
goal?: undefined;
|
|
412
|
+
decisions?: undefined;
|
|
413
|
+
confirmed?: undefined;
|
|
414
|
+
files?: undefined;
|
|
415
|
+
blocked?: undefined;
|
|
416
|
+
next?: undefined;
|
|
372
417
|
};
|
|
373
418
|
required: string[];
|
|
374
419
|
};
|
|
@@ -421,6 +466,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
421
466
|
show_docs?: undefined;
|
|
422
467
|
depth?: undefined;
|
|
423
468
|
scope?: undefined;
|
|
469
|
+
max_tokens?: undefined;
|
|
424
470
|
context_before?: undefined;
|
|
425
471
|
context_after?: undefined;
|
|
426
472
|
show?: undefined;
|
|
@@ -448,6 +494,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
448
494
|
command?: undefined;
|
|
449
495
|
runner?: undefined;
|
|
450
496
|
timeout?: undefined;
|
|
497
|
+
goal?: undefined;
|
|
498
|
+
decisions?: undefined;
|
|
499
|
+
confirmed?: undefined;
|
|
500
|
+
files?: undefined;
|
|
501
|
+
blocked?: undefined;
|
|
502
|
+
next?: undefined;
|
|
451
503
|
};
|
|
452
504
|
required: string[];
|
|
453
505
|
};
|
|
@@ -464,6 +516,10 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
464
516
|
};
|
|
465
517
|
description: string;
|
|
466
518
|
};
|
|
519
|
+
max_tokens: {
|
|
520
|
+
type: string;
|
|
521
|
+
description: string;
|
|
522
|
+
};
|
|
467
523
|
path?: undefined;
|
|
468
524
|
show_imports?: undefined;
|
|
469
525
|
show_docs?: undefined;
|
|
@@ -503,6 +559,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
503
559
|
command?: undefined;
|
|
504
560
|
runner?: undefined;
|
|
505
561
|
timeout?: undefined;
|
|
562
|
+
goal?: undefined;
|
|
563
|
+
decisions?: undefined;
|
|
564
|
+
confirmed?: undefined;
|
|
565
|
+
files?: undefined;
|
|
566
|
+
blocked?: undefined;
|
|
567
|
+
next?: undefined;
|
|
506
568
|
};
|
|
507
569
|
required: string[];
|
|
508
570
|
};
|
|
@@ -547,6 +609,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
547
609
|
show_imports?: undefined;
|
|
548
610
|
show_docs?: undefined;
|
|
549
611
|
depth?: undefined;
|
|
612
|
+
max_tokens?: undefined;
|
|
550
613
|
context_before?: undefined;
|
|
551
614
|
context_after?: undefined;
|
|
552
615
|
show?: undefined;
|
|
@@ -576,6 +639,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
576
639
|
command?: undefined;
|
|
577
640
|
runner?: undefined;
|
|
578
641
|
timeout?: undefined;
|
|
642
|
+
goal?: undefined;
|
|
643
|
+
decisions?: undefined;
|
|
644
|
+
confirmed?: undefined;
|
|
645
|
+
files?: undefined;
|
|
646
|
+
blocked?: undefined;
|
|
647
|
+
next?: undefined;
|
|
579
648
|
};
|
|
580
649
|
required: string[];
|
|
581
650
|
};
|
|
@@ -598,6 +667,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
598
667
|
show_docs?: undefined;
|
|
599
668
|
depth?: undefined;
|
|
600
669
|
scope?: undefined;
|
|
670
|
+
max_tokens?: undefined;
|
|
601
671
|
symbol?: undefined;
|
|
602
672
|
context_before?: undefined;
|
|
603
673
|
context_after?: undefined;
|
|
@@ -632,6 +702,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
632
702
|
command?: undefined;
|
|
633
703
|
runner?: undefined;
|
|
634
704
|
timeout?: undefined;
|
|
705
|
+
goal?: undefined;
|
|
706
|
+
decisions?: undefined;
|
|
707
|
+
confirmed?: undefined;
|
|
708
|
+
files?: undefined;
|
|
709
|
+
blocked?: undefined;
|
|
710
|
+
next?: undefined;
|
|
635
711
|
};
|
|
636
712
|
required?: undefined;
|
|
637
713
|
};
|
|
@@ -649,6 +725,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
649
725
|
show_docs?: undefined;
|
|
650
726
|
depth?: undefined;
|
|
651
727
|
scope?: undefined;
|
|
728
|
+
max_tokens?: undefined;
|
|
652
729
|
symbol?: undefined;
|
|
653
730
|
context_before?: undefined;
|
|
654
731
|
context_after?: undefined;
|
|
@@ -684,6 +761,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
684
761
|
command?: undefined;
|
|
685
762
|
runner?: undefined;
|
|
686
763
|
timeout?: undefined;
|
|
764
|
+
goal?: undefined;
|
|
765
|
+
decisions?: undefined;
|
|
766
|
+
confirmed?: undefined;
|
|
767
|
+
files?: undefined;
|
|
768
|
+
blocked?: undefined;
|
|
769
|
+
next?: undefined;
|
|
687
770
|
};
|
|
688
771
|
required: string[];
|
|
689
772
|
};
|
|
@@ -709,6 +792,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
709
792
|
show_docs?: undefined;
|
|
710
793
|
depth?: undefined;
|
|
711
794
|
scope?: undefined;
|
|
795
|
+
max_tokens?: undefined;
|
|
712
796
|
symbol?: undefined;
|
|
713
797
|
context_before?: undefined;
|
|
714
798
|
context_after?: undefined;
|
|
@@ -742,6 +826,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
742
826
|
command?: undefined;
|
|
743
827
|
runner?: undefined;
|
|
744
828
|
timeout?: undefined;
|
|
829
|
+
goal?: undefined;
|
|
830
|
+
decisions?: undefined;
|
|
831
|
+
confirmed?: undefined;
|
|
832
|
+
files?: undefined;
|
|
833
|
+
blocked?: undefined;
|
|
834
|
+
next?: undefined;
|
|
745
835
|
};
|
|
746
836
|
required: string[];
|
|
747
837
|
};
|
|
@@ -760,6 +850,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
760
850
|
show_docs?: undefined;
|
|
761
851
|
depth?: undefined;
|
|
762
852
|
scope?: undefined;
|
|
853
|
+
max_tokens?: undefined;
|
|
763
854
|
symbol?: undefined;
|
|
764
855
|
context_before?: undefined;
|
|
765
856
|
context_after?: undefined;
|
|
@@ -794,6 +885,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
794
885
|
command?: undefined;
|
|
795
886
|
runner?: undefined;
|
|
796
887
|
timeout?: undefined;
|
|
888
|
+
goal?: undefined;
|
|
889
|
+
decisions?: undefined;
|
|
890
|
+
confirmed?: undefined;
|
|
891
|
+
files?: undefined;
|
|
892
|
+
blocked?: undefined;
|
|
893
|
+
next?: undefined;
|
|
797
894
|
};
|
|
798
895
|
required?: undefined;
|
|
799
896
|
};
|
|
@@ -820,6 +917,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
820
917
|
show_docs?: undefined;
|
|
821
918
|
depth?: undefined;
|
|
822
919
|
scope?: undefined;
|
|
920
|
+
max_tokens?: undefined;
|
|
823
921
|
symbol?: undefined;
|
|
824
922
|
context_before?: undefined;
|
|
825
923
|
context_after?: undefined;
|
|
@@ -852,6 +950,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
852
950
|
command?: undefined;
|
|
853
951
|
runner?: undefined;
|
|
854
952
|
timeout?: undefined;
|
|
953
|
+
goal?: undefined;
|
|
954
|
+
decisions?: undefined;
|
|
955
|
+
confirmed?: undefined;
|
|
956
|
+
files?: undefined;
|
|
957
|
+
blocked?: undefined;
|
|
958
|
+
next?: undefined;
|
|
855
959
|
};
|
|
856
960
|
required?: undefined;
|
|
857
961
|
};
|
|
@@ -887,6 +991,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
887
991
|
show_docs?: undefined;
|
|
888
992
|
depth?: undefined;
|
|
889
993
|
scope?: undefined;
|
|
994
|
+
max_tokens?: undefined;
|
|
890
995
|
symbol?: undefined;
|
|
891
996
|
context_before?: undefined;
|
|
892
997
|
context_after?: undefined;
|
|
@@ -917,6 +1022,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
917
1022
|
command?: undefined;
|
|
918
1023
|
runner?: undefined;
|
|
919
1024
|
timeout?: undefined;
|
|
1025
|
+
goal?: undefined;
|
|
1026
|
+
decisions?: undefined;
|
|
1027
|
+
confirmed?: undefined;
|
|
1028
|
+
files?: undefined;
|
|
1029
|
+
blocked?: undefined;
|
|
1030
|
+
next?: undefined;
|
|
920
1031
|
};
|
|
921
1032
|
required: string[];
|
|
922
1033
|
};
|
|
@@ -940,6 +1051,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
940
1051
|
show_docs?: undefined;
|
|
941
1052
|
depth?: undefined;
|
|
942
1053
|
scope?: undefined;
|
|
1054
|
+
max_tokens?: undefined;
|
|
943
1055
|
symbol?: undefined;
|
|
944
1056
|
context_before?: undefined;
|
|
945
1057
|
context_after?: undefined;
|
|
@@ -973,6 +1085,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
973
1085
|
command?: undefined;
|
|
974
1086
|
runner?: undefined;
|
|
975
1087
|
timeout?: undefined;
|
|
1088
|
+
goal?: undefined;
|
|
1089
|
+
decisions?: undefined;
|
|
1090
|
+
confirmed?: undefined;
|
|
1091
|
+
files?: undefined;
|
|
1092
|
+
blocked?: undefined;
|
|
1093
|
+
next?: undefined;
|
|
976
1094
|
};
|
|
977
1095
|
required: string[];
|
|
978
1096
|
};
|
|
@@ -998,6 +1116,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
998
1116
|
show_imports?: undefined;
|
|
999
1117
|
show_docs?: undefined;
|
|
1000
1118
|
depth?: undefined;
|
|
1119
|
+
max_tokens?: undefined;
|
|
1001
1120
|
symbol?: undefined;
|
|
1002
1121
|
context_before?: undefined;
|
|
1003
1122
|
context_after?: undefined;
|
|
@@ -1032,6 +1151,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1032
1151
|
command?: undefined;
|
|
1033
1152
|
runner?: undefined;
|
|
1034
1153
|
timeout?: undefined;
|
|
1154
|
+
goal?: undefined;
|
|
1155
|
+
decisions?: undefined;
|
|
1156
|
+
confirmed?: undefined;
|
|
1157
|
+
files?: undefined;
|
|
1158
|
+
blocked?: undefined;
|
|
1159
|
+
next?: undefined;
|
|
1035
1160
|
};
|
|
1036
1161
|
required?: undefined;
|
|
1037
1162
|
};
|
|
@@ -1057,6 +1182,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1057
1182
|
show_docs?: undefined;
|
|
1058
1183
|
depth?: undefined;
|
|
1059
1184
|
scope?: undefined;
|
|
1185
|
+
max_tokens?: undefined;
|
|
1060
1186
|
symbol?: undefined;
|
|
1061
1187
|
context_before?: undefined;
|
|
1062
1188
|
context_after?: undefined;
|
|
@@ -1091,6 +1217,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1091
1217
|
command?: undefined;
|
|
1092
1218
|
runner?: undefined;
|
|
1093
1219
|
timeout?: undefined;
|
|
1220
|
+
goal?: undefined;
|
|
1221
|
+
decisions?: undefined;
|
|
1222
|
+
confirmed?: undefined;
|
|
1223
|
+
files?: undefined;
|
|
1224
|
+
blocked?: undefined;
|
|
1225
|
+
next?: undefined;
|
|
1094
1226
|
};
|
|
1095
1227
|
required: string[];
|
|
1096
1228
|
};
|
|
@@ -1116,6 +1248,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1116
1248
|
show_docs?: undefined;
|
|
1117
1249
|
depth?: undefined;
|
|
1118
1250
|
scope?: undefined;
|
|
1251
|
+
max_tokens?: undefined;
|
|
1119
1252
|
symbol?: undefined;
|
|
1120
1253
|
context_before?: undefined;
|
|
1121
1254
|
context_after?: undefined;
|
|
@@ -1149,6 +1282,12 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1149
1282
|
command?: undefined;
|
|
1150
1283
|
runner?: undefined;
|
|
1151
1284
|
timeout?: undefined;
|
|
1285
|
+
goal?: undefined;
|
|
1286
|
+
decisions?: undefined;
|
|
1287
|
+
confirmed?: undefined;
|
|
1288
|
+
files?: undefined;
|
|
1289
|
+
blocked?: undefined;
|
|
1290
|
+
next?: undefined;
|
|
1152
1291
|
};
|
|
1153
1292
|
required?: undefined;
|
|
1154
1293
|
};
|
|
@@ -1176,6 +1315,93 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1176
1315
|
show_docs?: undefined;
|
|
1177
1316
|
depth?: undefined;
|
|
1178
1317
|
scope?: undefined;
|
|
1318
|
+
max_tokens?: undefined;
|
|
1319
|
+
symbol?: undefined;
|
|
1320
|
+
context_before?: undefined;
|
|
1321
|
+
context_after?: undefined;
|
|
1322
|
+
show?: undefined;
|
|
1323
|
+
include_edit_context?: undefined;
|
|
1324
|
+
symbols?: undefined;
|
|
1325
|
+
start_line?: undefined;
|
|
1326
|
+
end_line?: undefined;
|
|
1327
|
+
heading?: undefined;
|
|
1328
|
+
context_lines?: undefined;
|
|
1329
|
+
line?: undefined;
|
|
1330
|
+
context?: undefined;
|
|
1331
|
+
include_callers?: undefined;
|
|
1332
|
+
include_tests?: undefined;
|
|
1333
|
+
include_changes?: undefined;
|
|
1334
|
+
section?: undefined;
|
|
1335
|
+
paths?: undefined;
|
|
1336
|
+
kind?: undefined;
|
|
1337
|
+
limit?: undefined;
|
|
1338
|
+
lang?: undefined;
|
|
1339
|
+
mode?: undefined;
|
|
1340
|
+
include?: undefined;
|
|
1341
|
+
recursive?: undefined;
|
|
1342
|
+
max_depth?: undefined;
|
|
1343
|
+
verbose?: undefined;
|
|
1344
|
+
module?: undefined;
|
|
1345
|
+
export_only?: undefined;
|
|
1346
|
+
check?: undefined;
|
|
1347
|
+
pattern?: undefined;
|
|
1348
|
+
name?: undefined;
|
|
1349
|
+
ref?: undefined;
|
|
1350
|
+
count?: undefined;
|
|
1351
|
+
goal?: undefined;
|
|
1352
|
+
decisions?: undefined;
|
|
1353
|
+
confirmed?: undefined;
|
|
1354
|
+
files?: undefined;
|
|
1355
|
+
blocked?: undefined;
|
|
1356
|
+
next?: undefined;
|
|
1357
|
+
};
|
|
1358
|
+
required: string[];
|
|
1359
|
+
};
|
|
1360
|
+
} | {
|
|
1361
|
+
name: string;
|
|
1362
|
+
description: string;
|
|
1363
|
+
inputSchema: {
|
|
1364
|
+
type: "object";
|
|
1365
|
+
properties: {
|
|
1366
|
+
goal: {
|
|
1367
|
+
type: string;
|
|
1368
|
+
description: string;
|
|
1369
|
+
};
|
|
1370
|
+
decisions: {
|
|
1371
|
+
type: string;
|
|
1372
|
+
items: {
|
|
1373
|
+
type: string;
|
|
1374
|
+
};
|
|
1375
|
+
description: string;
|
|
1376
|
+
};
|
|
1377
|
+
confirmed: {
|
|
1378
|
+
type: string;
|
|
1379
|
+
items: {
|
|
1380
|
+
type: string;
|
|
1381
|
+
};
|
|
1382
|
+
description: string;
|
|
1383
|
+
};
|
|
1384
|
+
files: {
|
|
1385
|
+
type: string;
|
|
1386
|
+
items: {
|
|
1387
|
+
type: string;
|
|
1388
|
+
};
|
|
1389
|
+
description: string;
|
|
1390
|
+
};
|
|
1391
|
+
blocked: {
|
|
1392
|
+
type: string;
|
|
1393
|
+
description: string;
|
|
1394
|
+
};
|
|
1395
|
+
next: {
|
|
1396
|
+
type: string;
|
|
1397
|
+
description: string;
|
|
1398
|
+
};
|
|
1399
|
+
path?: undefined;
|
|
1400
|
+
show_imports?: undefined;
|
|
1401
|
+
show_docs?: undefined;
|
|
1402
|
+
depth?: undefined;
|
|
1403
|
+
scope?: undefined;
|
|
1404
|
+
max_tokens?: undefined;
|
|
1179
1405
|
symbol?: undefined;
|
|
1180
1406
|
context_before?: undefined;
|
|
1181
1407
|
context_after?: undefined;
|
|
@@ -1208,6 +1434,9 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1208
1434
|
name?: undefined;
|
|
1209
1435
|
ref?: undefined;
|
|
1210
1436
|
count?: undefined;
|
|
1437
|
+
command?: undefined;
|
|
1438
|
+
runner?: undefined;
|
|
1439
|
+
timeout?: undefined;
|
|
1211
1440
|
};
|
|
1212
1441
|
required: string[];
|
|
1213
1442
|
};
|
|
@@ -29,6 +29,8 @@ export const MCP_INSTRUCTIONS = [
|
|
|
29
29
|
'17. Module architecture → module_info (deps, dependents, public API)',
|
|
30
30
|
'18. Read markdown/yaml/json/csv section → read_section (loads one heading/key/row-range, NOT the whole file)',
|
|
31
31
|
' - For editing sections: read_for_edit(path, section="Section Name")',
|
|
32
|
+
'19. Long session / before compaction → session_snapshot (capture goal, decisions, confirmed facts, files, next step as <200 token block)',
|
|
33
|
+
' - Budget-constrained? Use smart_read(max_tokens=N) to auto-downgrade output size',
|
|
32
34
|
'',
|
|
33
35
|
'USE DEFAULT TOOLS ONLY FOR: regex text search → Grep | exact raw content → Read | non-code configs → Read',
|
|
34
36
|
'',
|
|
@@ -38,6 +40,7 @@ export const MCP_INSTRUCTIONS = [
|
|
|
38
40
|
'• Docs: smart_read (outline) → read_section → read_for_edit(section=) → Edit → read_diff',
|
|
39
41
|
'• Refactor: find_usages → read_symbols → read_for_edit → Edit → test_summary',
|
|
40
42
|
'• Audit: code_audit + find_unused + Grep (for regex patterns)',
|
|
43
|
+
'• Long session: session_snapshot → compact context → continue with minimal state',
|
|
41
44
|
].join('\n');
|
|
42
45
|
export const TOOL_DEFINITIONS = [
|
|
43
46
|
// --- Core reading tools ---
|
|
@@ -56,6 +59,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
56
59
|
enum: ['full', 'nav', 'exports'],
|
|
57
60
|
description: 'Output scope: full (default, all details), nav (names + lines only, 2-3x smaller), exports (public API only)',
|
|
58
61
|
},
|
|
62
|
+
max_tokens: { type: 'number', description: 'Token budget. If output exceeds this, auto-downgrades: full → outline → compact. Use for context-constrained sessions.' },
|
|
59
63
|
},
|
|
60
64
|
required: ['path'],
|
|
61
65
|
},
|
|
@@ -172,6 +176,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
172
176
|
items: { type: 'string' },
|
|
173
177
|
description: 'Array of file paths',
|
|
174
178
|
},
|
|
179
|
+
max_tokens: { type: 'number', description: 'Token budget per file. If a file exceeds this, auto-downgrades to compact outline.' },
|
|
175
180
|
},
|
|
176
181
|
required: ['paths'],
|
|
177
182
|
},
|
|
@@ -349,5 +354,22 @@ export const TOOL_DEFINITIONS = [
|
|
|
349
354
|
required: ['command'],
|
|
350
355
|
},
|
|
351
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
|
+
decisions: { type: 'array', items: { type: 'string' }, description: 'Key decisions made and why (e.g., "removed sysfee step — caused double counting"). Prevents revisiting rejected approaches.' },
|
|
366
|
+
confirmed: { type: 'array', items: { type: 'string' }, description: 'Established facts (what has been verified)' },
|
|
367
|
+
files: { type: 'array', items: { type: 'string' }, description: 'Relevant file paths' },
|
|
368
|
+
blocked: { type: 'string', description: 'Current blocker or obstacle' },
|
|
369
|
+
next: { type: 'string', description: 'Next step to take' },
|
|
370
|
+
},
|
|
371
|
+
required: ['goal'],
|
|
372
|
+
},
|
|
373
|
+
},
|
|
352
374
|
];
|
|
353
375
|
//# sourceMappingURL=tool-definitions.js.map
|
package/dist/server.js
CHANGED
|
@@ -36,6 +36,7 @@ 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';
|
|
39
40
|
import { handleReadSection } from './handlers/read-section.js';
|
|
40
41
|
import { detectContextMode } from './integration/context-mode-detector.js';
|
|
41
42
|
import { estimateTokens } from './core/token-estimator.js';
|
|
@@ -154,6 +155,8 @@ export async function createServer(projectRoot, options) {
|
|
|
154
155
|
: null;
|
|
155
156
|
// Policy engine state
|
|
156
157
|
let fullFileReadsCount = 0;
|
|
158
|
+
let totalCallCount = 0;
|
|
159
|
+
let totalTokensReturned = 0;
|
|
157
160
|
const readForEditCalled = new Set();
|
|
158
161
|
// Detect context-mode companion
|
|
159
162
|
const cmEnabled = config.contextMode.enabled;
|
|
@@ -224,6 +227,8 @@ export async function createServer(projectRoot, options) {
|
|
|
224
227
|
}),
|
|
225
228
|
});
|
|
226
229
|
// Policy tracking
|
|
230
|
+
totalCallCount++;
|
|
231
|
+
totalTokensReturned += rest.tokensReturned;
|
|
227
232
|
if (isFullReadTool(rest.tool)) {
|
|
228
233
|
fullFileReadsCount++;
|
|
229
234
|
}
|
|
@@ -235,6 +240,8 @@ export async function createServer(projectRoot, options) {
|
|
|
235
240
|
fullFileReadsCount,
|
|
236
241
|
tokensReturned: rest.tokensReturned,
|
|
237
242
|
readForEditCalled,
|
|
243
|
+
totalCallCount,
|
|
244
|
+
totalTokensReturned,
|
|
238
245
|
});
|
|
239
246
|
return advisory ? `\n${advisory.message}` : null;
|
|
240
247
|
}
|
|
@@ -575,6 +582,17 @@ export async function createServer(projectRoot, options) {
|
|
|
575
582
|
recordWithTrace({ tool: 'test_summary', path: tsArgs.command, tokensReturned: tsTokens, tokensWouldBe: tsResult.rawTokens || tsTokens, timestamp: Date.now(), savingsCategory: 'compression', args: tsArgs });
|
|
576
583
|
return { content: tsResult.content };
|
|
577
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
|
+
}
|
|
578
596
|
default:
|
|
579
597
|
return {
|
|
580
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.1",
|
|
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",
|