token-pilot 0.29.0 → 0.30.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 +35 -0
- package/README.md +39 -390
- package/agents/tp-api-surface-tracker.md +1 -1
- package/agents/tp-audit-scanner.md +1 -1
- package/agents/tp-commit-writer.md +1 -1
- package/agents/tp-context-engineer.md +1 -1
- package/agents/tp-dead-code-finder.md +1 -1
- package/agents/tp-debugger.md +1 -1
- package/agents/tp-dep-health.md +1 -1
- package/agents/tp-doc-writer.md +1 -1
- package/agents/tp-history-explorer.md +1 -1
- package/agents/tp-impact-analyzer.md +1 -1
- package/agents/tp-incident-timeline.md +1 -1
- package/agents/tp-incremental-builder.md +1 -1
- package/agents/tp-migration-scout.md +1 -1
- package/agents/tp-onboard.md +1 -1
- package/agents/tp-performance-profiler.md +1 -1
- package/agents/tp-pr-reviewer.md +1 -1
- package/agents/tp-refactor-planner.md +1 -1
- package/agents/tp-review-impact.md +1 -1
- package/agents/tp-run.md +1 -1
- package/agents/tp-session-restorer.md +1 -1
- package/agents/tp-ship-coordinator.md +1 -1
- package/agents/tp-spec-writer.md +1 -1
- package/agents/tp-test-coverage-gapper.md +1 -1
- package/agents/tp-test-triage.md +1 -1
- package/agents/tp-test-writer.md +1 -1
- package/dist/cli/tool-audit.d.ts +5 -0
- package/dist/cli/tool-audit.js +9 -1
- package/dist/core/policy-engine.d.ts +1 -5
- package/dist/core/policy-engine.js +9 -24
- package/dist/hooks/pre-bash.d.ts +2 -1
- package/dist/hooks/pre-bash.js +3 -1
- package/dist/hooks/pre-grep.d.ts +2 -1
- package/dist/hooks/pre-grep.js +3 -1
- package/dist/index.js +4 -2
- package/dist/server/enforcement-mode.d.ts +47 -0
- package/dist/server/enforcement-mode.js +59 -0
- package/dist/server/tool-definitions.d.ts +20 -0
- package/dist/server/tool-definitions.js +111 -8
- package/dist/server/tool-profiles.d.ts +19 -1
- package/dist/server/tool-profiles.js +38 -4
- package/dist/server.d.ts +2 -0
- package/dist/server.js +68 -16
- package/docs/agents.md +82 -0
- package/docs/configuration.md +117 -0
- package/docs/hooks.md +99 -0
- package/docs/installation.md +143 -0
- package/docs/tools.md +61 -0
- package/package.json +2 -2
package/agents/tp-onboard.md
CHANGED
|
@@ -10,7 +10,7 @@ tools:
|
|
|
10
10
|
- mcp__token-pilot__smart_read
|
|
11
11
|
- mcp__token-pilot__smart_read_many
|
|
12
12
|
- mcp__token-pilot__read_section
|
|
13
|
-
token_pilot_version: "0.
|
|
13
|
+
token_pilot_version: "0.30.0"
|
|
14
14
|
token_pilot_body_hash: 4e82f7b3c6446663e958fb6bf5eb5348bbdf33389269c888ce0dab766e50561f
|
|
15
15
|
---
|
|
16
16
|
|
package/agents/tp-pr-reviewer.md
CHANGED
package/agents/tp-run.md
CHANGED
package/agents/tp-spec-writer.md
CHANGED
package/agents/tp-test-triage.md
CHANGED
package/agents/tp-test-writer.md
CHANGED
package/dist/cli/tool-audit.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export interface ToolAuditRow {
|
|
|
22
22
|
/** Calls where the recorder claimed NO savings (pass-through) — separate so
|
|
23
23
|
* they don't poison the reduction average. */
|
|
24
24
|
noneCalls: number;
|
|
25
|
+
/** Calls where the MCP response was served from the session cache (the model
|
|
26
|
+
* replayed cached tokens). These contribute to `saved` but the mechanism
|
|
27
|
+
* is token re-use, not structural compression — useful to split out so the
|
|
28
|
+
* "Est.Saved*" column is understood correctly. */
|
|
29
|
+
cacheHitCalls: number;
|
|
25
30
|
/** True when reduction is below the low-value threshold AND we have enough
|
|
26
31
|
* samples (≥5) to make a claim — avoids flagging tools after 1 bad run. */
|
|
27
32
|
lowValue: boolean;
|
package/dist/cli/tool-audit.js
CHANGED
|
@@ -24,12 +24,15 @@ export function aggregateToolCalls(events, lowValueThreshold = 20, minSamples =
|
|
|
24
24
|
tokensReturned: 0,
|
|
25
25
|
tokensWouldBe: 0,
|
|
26
26
|
noneCalls: 0,
|
|
27
|
+
cacheHitCalls: 0,
|
|
27
28
|
};
|
|
28
29
|
row.count++;
|
|
29
30
|
row.tokensReturned += e.tokensReturned;
|
|
30
31
|
row.tokensWouldBe += e.tokensWouldBe;
|
|
31
32
|
if (e.savingsCategory === "none")
|
|
32
33
|
row.noneCalls++;
|
|
34
|
+
if (e.sessionCacheHit)
|
|
35
|
+
row.cacheHitCalls++;
|
|
33
36
|
byTool.set(e.tool, row);
|
|
34
37
|
}
|
|
35
38
|
const rows = [];
|
|
@@ -47,6 +50,7 @@ export function aggregateToolCalls(events, lowValueThreshold = 20, minSamples =
|
|
|
47
50
|
saved,
|
|
48
51
|
reductionPct,
|
|
49
52
|
noneCalls: r.noneCalls,
|
|
53
|
+
cacheHitCalls: r.cacheHitCalls,
|
|
50
54
|
lowValue,
|
|
51
55
|
});
|
|
52
56
|
}
|
|
@@ -74,7 +78,7 @@ Run a few MCP tool calls from your AI client, then re-run \`npx token-pilot tool
|
|
|
74
78
|
lines.push(`Token Pilot — tool audit`);
|
|
75
79
|
lines.push(` ${opts.totalEvents} calls across ${rows.length} tools (cumulative across sessions)`);
|
|
76
80
|
lines.push("");
|
|
77
|
-
lines.push(" Tool Calls
|
|
81
|
+
lines.push(" Tool Calls Est.Saved* Returned Reduction");
|
|
78
82
|
lines.push(" ─────────────────────────────────────────────────────────────────");
|
|
79
83
|
for (const r of rows) {
|
|
80
84
|
const tool = r.tool.padEnd(24);
|
|
@@ -91,6 +95,10 @@ Run a few MCP tool calls from your AI client, then re-run \`npx token-pilot tool
|
|
|
91
95
|
lines.push("Low-value tools flagged above have <20% token reduction across ≥5 calls.");
|
|
92
96
|
lines.push("Consider: check their `none` passthrough count, or whether a cheaper alternative (Grep, Read) would do the job.");
|
|
93
97
|
}
|
|
98
|
+
lines.push("");
|
|
99
|
+
lines.push("* Est.Saved is estimated against a full-file read baseline. Actual prompt");
|
|
100
|
+
lines.push(" savings depend on client caching — use `cacheHitCalls` in --json output");
|
|
101
|
+
lines.push(" to distinguish structural compression from cache re-use.");
|
|
94
102
|
return lines.join("\n");
|
|
95
103
|
}
|
|
96
104
|
export async function runToolAudit(opts) {
|
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
export interface PolicyConfig {
|
|
7
7
|
/** Advisory hints when an expensive tool is used where a cheaper alternative exists */
|
|
8
8
|
preferCheapReads: boolean;
|
|
9
|
-
/** Track if read_for_edit was called before edit (advisory) */
|
|
10
|
-
requireReadForEditBeforeEdit: boolean;
|
|
11
9
|
/** Always cache project overview in session cache */
|
|
12
10
|
cacheProjectOverview: boolean;
|
|
13
11
|
/** Warn after N full-file reads in a session */
|
|
@@ -25,13 +23,11 @@ export declare const DEFAULT_POLICIES: PolicyConfig;
|
|
|
25
23
|
export interface PolicyCheckContext {
|
|
26
24
|
fullFileReadsCount: number;
|
|
27
25
|
tokensReturned: number;
|
|
28
|
-
readForEditCalled?: Set<string>;
|
|
29
|
-
editTargetPath?: string;
|
|
30
26
|
totalCallCount?: number;
|
|
31
27
|
totalTokensReturned?: number;
|
|
32
28
|
}
|
|
33
29
|
export interface PolicyAdvisory {
|
|
34
|
-
level:
|
|
30
|
+
level: "info" | "warn";
|
|
35
31
|
message: string;
|
|
36
32
|
}
|
|
37
33
|
/**
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export const DEFAULT_POLICIES = {
|
|
7
7
|
preferCheapReads: true,
|
|
8
|
-
requireReadForEditBeforeEdit: true,
|
|
9
8
|
cacheProjectOverview: true,
|
|
10
9
|
maxFullFileReads: 10,
|
|
11
10
|
warnOnLargeReads: true,
|
|
@@ -14,14 +13,11 @@ export const DEFAULT_POLICIES = {
|
|
|
14
13
|
compactionTokenThreshold: 8000,
|
|
15
14
|
};
|
|
16
15
|
/** Full-file read tools that count toward maxFullFileReads */
|
|
17
|
-
const FULL_READ_TOOLS = new Set([
|
|
18
|
-
'smart_read',
|
|
19
|
-
'smart_read_many',
|
|
20
|
-
]);
|
|
16
|
+
const FULL_READ_TOOLS = new Set(["smart_read", "smart_read_many"]);
|
|
21
17
|
/** Tools that indicate a cheaper alternative may exist */
|
|
22
18
|
const EXPENSIVE_TOOLS = {
|
|
23
|
-
smart_read:
|
|
24
|
-
smart_read_many:
|
|
19
|
+
smart_read: "Consider read_symbol() or read_range() for targeted reads",
|
|
20
|
+
smart_read_many: "Consider reading files individually with read_symbol()",
|
|
25
21
|
};
|
|
26
22
|
/**
|
|
27
23
|
* Check policy rules and return advisory messages.
|
|
@@ -33,7 +29,7 @@ export function checkPolicy(policy, tool, context) {
|
|
|
33
29
|
FULL_READ_TOOLS.has(tool) &&
|
|
34
30
|
context.fullFileReadsCount >= policy.maxFullFileReads) {
|
|
35
31
|
return {
|
|
36
|
-
level:
|
|
32
|
+
level: "warn",
|
|
37
33
|
message: `POLICY: ${context.fullFileReadsCount} full-file reads this session (limit: ${policy.maxFullFileReads}). Consider read_symbol() or read_range() for targeted access.`,
|
|
38
34
|
};
|
|
39
35
|
}
|
|
@@ -41,7 +37,7 @@ export function checkPolicy(policy, tool, context) {
|
|
|
41
37
|
if (policy.warnOnLargeReads &&
|
|
42
38
|
context.tokensReturned > policy.largeReadThreshold) {
|
|
43
39
|
return {
|
|
44
|
-
level:
|
|
40
|
+
level: "info",
|
|
45
41
|
message: `POLICY: Large response (~${context.tokensReturned} tokens). Future reads on this file: use read_symbol() or read_range() for targeted access.`,
|
|
46
42
|
};
|
|
47
43
|
}
|
|
@@ -50,29 +46,18 @@ export function checkPolicy(policy, tool, context) {
|
|
|
50
46
|
// Only advise when token count is high enough to matter
|
|
51
47
|
if (context.tokensReturned > 500) {
|
|
52
48
|
return {
|
|
53
|
-
level:
|
|
49
|
+
level: "info",
|
|
54
50
|
message: `POLICY: ${EXPENSIVE_TOOLS[tool]}`,
|
|
55
51
|
};
|
|
56
52
|
}
|
|
57
53
|
}
|
|
58
|
-
// 4.
|
|
59
|
-
if (policy.requireReadForEditBeforeEdit &&
|
|
60
|
-
tool === 'edit' &&
|
|
61
|
-
context.editTargetPath &&
|
|
62
|
-
context.readForEditCalled &&
|
|
63
|
-
!context.readForEditCalled.has(context.editTargetPath)) {
|
|
64
|
-
return {
|
|
65
|
-
level: 'info',
|
|
66
|
-
message: `POLICY: Consider using read_for_edit("${context.editTargetPath}") before editing to get precise edit context.`,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// 5. Session compaction advisory — by call count
|
|
54
|
+
// 4. Session compaction advisory — by call count
|
|
70
55
|
if (policy.compactionCallThreshold > 0 &&
|
|
71
56
|
context.totalCallCount !== undefined &&
|
|
72
57
|
context.totalCallCount > 0 &&
|
|
73
58
|
context.totalCallCount % policy.compactionCallThreshold === 0) {
|
|
74
59
|
return {
|
|
75
|
-
level:
|
|
60
|
+
level: "info",
|
|
76
61
|
message: `COMPACTION: ${context.totalCallCount} tool calls this session. Consider calling session_snapshot() to capture state, then compact context.`,
|
|
77
62
|
};
|
|
78
63
|
}
|
|
@@ -84,7 +69,7 @@ export function checkPolicy(policy, tool, context) {
|
|
|
84
69
|
context.totalCallCount % 5 === 0 // don't spam every call, check every 5th
|
|
85
70
|
) {
|
|
86
71
|
return {
|
|
87
|
-
level:
|
|
72
|
+
level: "info",
|
|
88
73
|
message: `COMPACTION: ~${context.totalTokensReturned} tokens returned this session. Consider calling session_snapshot() to capture state, then compact context.`,
|
|
89
74
|
};
|
|
90
75
|
}
|
package/dist/hooks/pre-bash.d.ts
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* `bash -c`, heredocs, or eval'd strings slip through. Acceptable for
|
|
25
25
|
* v0.28.0; tighten only if tool-audit shows repeated escapes.
|
|
26
26
|
*/
|
|
27
|
+
import type { EnforcementMode } from "../server/enforcement-mode.js";
|
|
27
28
|
export interface PreBashInput {
|
|
28
29
|
tool_name?: string;
|
|
29
30
|
tool_input?: {
|
|
@@ -49,6 +50,6 @@ export type PreBashDecision = {
|
|
|
49
50
|
*/
|
|
50
51
|
export declare function extractWrappedCommands(command: string): string[];
|
|
51
52
|
export declare function detectHeavyPattern(command: string): PreBashDecision;
|
|
52
|
-
export declare function decidePreBash(input: PreBashInput): PreBashDecision;
|
|
53
|
+
export declare function decidePreBash(input: PreBashInput, mode?: EnforcementMode): PreBashDecision;
|
|
53
54
|
export declare function renderPreBashOutput(decision: PreBashDecision): string | null;
|
|
54
55
|
//# sourceMappingURL=pre-bash.d.ts.map
|
package/dist/hooks/pre-bash.js
CHANGED
|
@@ -143,7 +143,9 @@ function detectHeavyPatternSingle(command) {
|
|
|
143
143
|
}
|
|
144
144
|
return { kind: "allow" };
|
|
145
145
|
}
|
|
146
|
-
export function decidePreBash(input) {
|
|
146
|
+
export function decidePreBash(input, mode = "deny") {
|
|
147
|
+
if (mode === "advisory")
|
|
148
|
+
return { kind: "allow" };
|
|
147
149
|
if (input.tool_name !== "Bash")
|
|
148
150
|
return { kind: "allow" };
|
|
149
151
|
const cmd = input.tool_input?.command;
|
package/dist/hooks/pre-grep.d.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* find_usages after the block, we keep it. If they bypass via `-E` or
|
|
21
21
|
* raw shell, we soften to advisory.
|
|
22
22
|
*/
|
|
23
|
+
import type { EnforcementMode } from "../server/enforcement-mode.js";
|
|
23
24
|
export interface PreGrepInput {
|
|
24
25
|
tool_name?: string;
|
|
25
26
|
tool_input?: {
|
|
@@ -51,7 +52,7 @@ export declare function isSymbolLikePattern(pattern: string): boolean;
|
|
|
51
52
|
* Pure decision function. Given a PreToolUse hook input for Grep,
|
|
52
53
|
* return whether to allow or deny (with a suggestion).
|
|
53
54
|
*/
|
|
54
|
-
export declare function decidePreGrep(input: PreGrepInput): PreGrepDecision;
|
|
55
|
+
export declare function decidePreGrep(input: PreGrepInput, mode?: EnforcementMode): PreGrepDecision;
|
|
55
56
|
/**
|
|
56
57
|
* Render the Claude Code hook JSON response.
|
|
57
58
|
*/
|
package/dist/hooks/pre-grep.js
CHANGED
|
@@ -64,7 +64,9 @@ export function isSymbolLikePattern(pattern) {
|
|
|
64
64
|
* Pure decision function. Given a PreToolUse hook input for Grep,
|
|
65
65
|
* return whether to allow or deny (with a suggestion).
|
|
66
66
|
*/
|
|
67
|
-
export function decidePreGrep(input) {
|
|
67
|
+
export function decidePreGrep(input, mode = "deny") {
|
|
68
|
+
if (mode === "advisory")
|
|
69
|
+
return { kind: "allow" };
|
|
68
70
|
if (input.tool_name !== "Grep")
|
|
69
71
|
return { kind: "allow" };
|
|
70
72
|
const pattern = input.tool_input?.pattern;
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ import { assessClaudeMd } from "./cli/claudemd-hygiene.js";
|
|
|
52
52
|
import { decidePostBashAdvice, renderPostBashHookOutput, } from "./hooks/post-bash.js";
|
|
53
53
|
import { decidePreBash, renderPreBashOutput } from "./hooks/pre-bash.js";
|
|
54
54
|
import { decidePreGrep, renderPreGrepOutput } from "./hooks/pre-grep.js";
|
|
55
|
+
import { parseEnforcementMode } from "./server/enforcement-mode.js";
|
|
55
56
|
const execFileAsync = promisify(execFile);
|
|
56
57
|
export const CODE_EXTENSIONS = new Set([
|
|
57
58
|
"ts",
|
|
@@ -152,7 +153,7 @@ export async function main(cliArgs = process.argv.slice(2)) {
|
|
|
152
153
|
try {
|
|
153
154
|
const stdin = readFileSync(0, "utf-8");
|
|
154
155
|
const input = JSON.parse(stdin);
|
|
155
|
-
const decision = decidePreBash(input);
|
|
156
|
+
const decision = decidePreBash(input, parseEnforcementMode(process.env.TOKEN_PILOT_MODE));
|
|
156
157
|
const rendered = renderPreBashOutput(decision);
|
|
157
158
|
if (rendered)
|
|
158
159
|
process.stdout.write(rendered);
|
|
@@ -169,7 +170,7 @@ export async function main(cliArgs = process.argv.slice(2)) {
|
|
|
169
170
|
try {
|
|
170
171
|
const stdin = readFileSync(0, "utf-8");
|
|
171
172
|
const input = JSON.parse(stdin);
|
|
172
|
-
const decision = decidePreGrep(input);
|
|
173
|
+
const decision = decidePreGrep(input, parseEnforcementMode(process.env.TOKEN_PILOT_MODE));
|
|
173
174
|
const rendered = renderPreGrepOutput(decision);
|
|
174
175
|
if (rendered)
|
|
175
176
|
process.stdout.write(rendered);
|
|
@@ -386,6 +387,7 @@ export async function startServer(cliArgs = process.argv.slice(2)) {
|
|
|
386
387
|
});
|
|
387
388
|
const server = await createServer(projectRoot, {
|
|
388
389
|
skipAstIndex: isDangerousRoot(projectRoot),
|
|
390
|
+
enforcementMode: parseEnforcementMode(process.env.TOKEN_PILOT_MODE),
|
|
389
391
|
});
|
|
390
392
|
const transport = new StdioServerTransport();
|
|
391
393
|
await server.connect(transport);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.30.0 — TOKEN_PILOT_MODE enforcement modes.
|
|
3
|
+
*
|
|
4
|
+
* Controls how aggressively token-pilot blocks heavy native tools and
|
|
5
|
+
* caps MCP tool output sizes. Three modes:
|
|
6
|
+
*
|
|
7
|
+
* advisory — hooks always allow, no MCP output caps. Observation-only.
|
|
8
|
+
* Use when measuring baseline token usage or debugging.
|
|
9
|
+
*
|
|
10
|
+
* deny — DEFAULT. Hooks deny heavy Bash/Grep patterns and suggest
|
|
11
|
+
* cheaper MCP alternatives. No auto-caps on MCP output.
|
|
12
|
+
* This is the "smart redirect" mode — the agent learns the
|
|
13
|
+
* right tool but can still produce large MCP responses.
|
|
14
|
+
*
|
|
15
|
+
* strict — deny + MCP output auto-caps. smart_read is capped at
|
|
16
|
+
* max_tokens=2000 when the caller doesn't set it; explore_area
|
|
17
|
+
* defaults include=['outline'] when the caller doesn't set it.
|
|
18
|
+
* Cap values are v0.30.0 initial estimates — tune from real
|
|
19
|
+
* tool-audit data in a follow-up PR (#8).
|
|
20
|
+
*
|
|
21
|
+
* Set via TOKEN_PILOT_MODE environment variable (case-insensitive, trimmed).
|
|
22
|
+
* Unknown values fall back to "deny" with a warning.
|
|
23
|
+
*
|
|
24
|
+
* Separate from `hooks.mode` (HookMode) which controls only the PreToolUse:Read
|
|
25
|
+
* hook (deny-enhanced vs advisory for large file reads). TOKEN_PILOT_MODE
|
|
26
|
+
* covers Bash and Grep hooks plus MCP output caps.
|
|
27
|
+
*/
|
|
28
|
+
export type EnforcementMode = "advisory" | "deny" | "strict";
|
|
29
|
+
export declare const ENFORCEMENT_MODE_NAMES: readonly ["advisory", "deny", "strict"];
|
|
30
|
+
/**
|
|
31
|
+
* Parse TOKEN_PILOT_MODE from an env-var string. Returns "deny" for
|
|
32
|
+
* missing or empty values. Emits a warning for unrecognised values.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseEnforcementMode(raw: string | undefined, warn?: (msg: string) => void): EnforcementMode;
|
|
35
|
+
/**
|
|
36
|
+
* The cap applied to smart_read max_tokens in strict mode when the
|
|
37
|
+
* caller has not supplied an explicit max_tokens.
|
|
38
|
+
* v0.30.0 initial estimate — tune from tool-audit data.
|
|
39
|
+
*/
|
|
40
|
+
export declare const STRICT_SMART_READ_MAX_TOKENS = 2000;
|
|
41
|
+
/**
|
|
42
|
+
* The include sections applied to explore_area in strict mode when the
|
|
43
|
+
* caller has not supplied an explicit include array.
|
|
44
|
+
* v0.30.0 initial estimate — outline-only keeps footprint minimal.
|
|
45
|
+
*/
|
|
46
|
+
export declare const STRICT_EXPLORE_AREA_INCLUDE: Array<"outline" | "imports" | "tests" | "changes">;
|
|
47
|
+
//# sourceMappingURL=enforcement-mode.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.30.0 — TOKEN_PILOT_MODE enforcement modes.
|
|
3
|
+
*
|
|
4
|
+
* Controls how aggressively token-pilot blocks heavy native tools and
|
|
5
|
+
* caps MCP tool output sizes. Three modes:
|
|
6
|
+
*
|
|
7
|
+
* advisory — hooks always allow, no MCP output caps. Observation-only.
|
|
8
|
+
* Use when measuring baseline token usage or debugging.
|
|
9
|
+
*
|
|
10
|
+
* deny — DEFAULT. Hooks deny heavy Bash/Grep patterns and suggest
|
|
11
|
+
* cheaper MCP alternatives. No auto-caps on MCP output.
|
|
12
|
+
* This is the "smart redirect" mode — the agent learns the
|
|
13
|
+
* right tool but can still produce large MCP responses.
|
|
14
|
+
*
|
|
15
|
+
* strict — deny + MCP output auto-caps. smart_read is capped at
|
|
16
|
+
* max_tokens=2000 when the caller doesn't set it; explore_area
|
|
17
|
+
* defaults include=['outline'] when the caller doesn't set it.
|
|
18
|
+
* Cap values are v0.30.0 initial estimates — tune from real
|
|
19
|
+
* tool-audit data in a follow-up PR (#8).
|
|
20
|
+
*
|
|
21
|
+
* Set via TOKEN_PILOT_MODE environment variable (case-insensitive, trimmed).
|
|
22
|
+
* Unknown values fall back to "deny" with a warning.
|
|
23
|
+
*
|
|
24
|
+
* Separate from `hooks.mode` (HookMode) which controls only the PreToolUse:Read
|
|
25
|
+
* hook (deny-enhanced vs advisory for large file reads). TOKEN_PILOT_MODE
|
|
26
|
+
* covers Bash and Grep hooks plus MCP output caps.
|
|
27
|
+
*/
|
|
28
|
+
export const ENFORCEMENT_MODE_NAMES = [
|
|
29
|
+
"advisory",
|
|
30
|
+
"deny",
|
|
31
|
+
"strict",
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Parse TOKEN_PILOT_MODE from an env-var string. Returns "deny" for
|
|
35
|
+
* missing or empty values. Emits a warning for unrecognised values.
|
|
36
|
+
*/
|
|
37
|
+
export function parseEnforcementMode(raw, warn = (m) => process.stderr.write(m + "\n")) {
|
|
38
|
+
if (!raw || raw.trim() === "")
|
|
39
|
+
return "deny";
|
|
40
|
+
const v = raw.trim().toLowerCase();
|
|
41
|
+
if (v === "advisory" || v === "deny" || v === "strict")
|
|
42
|
+
return v;
|
|
43
|
+
warn(`[token-pilot] Unknown TOKEN_PILOT_MODE="${raw}", falling back to "deny". ` +
|
|
44
|
+
`Valid values: advisory | deny | strict.`);
|
|
45
|
+
return "deny";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The cap applied to smart_read max_tokens in strict mode when the
|
|
49
|
+
* caller has not supplied an explicit max_tokens.
|
|
50
|
+
* v0.30.0 initial estimate — tune from tool-audit data.
|
|
51
|
+
*/
|
|
52
|
+
export const STRICT_SMART_READ_MAX_TOKENS = 2000;
|
|
53
|
+
/**
|
|
54
|
+
* The include sections applied to explore_area in strict mode when the
|
|
55
|
+
* caller has not supplied an explicit include array.
|
|
56
|
+
* v0.30.0 initial estimate — outline-only keeps footprint minimal.
|
|
57
|
+
*/
|
|
58
|
+
export const STRICT_EXPLORE_AREA_INCLUDE = ["outline"];
|
|
59
|
+
//# sourceMappingURL=enforcement-mode.js.map
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP tool definitions and system instructions.
|
|
3
3
|
* Pure static data — no runtime dependencies.
|
|
4
|
+
*
|
|
5
|
+
* v0.30.0 — Profile-specific instructions. Each profile advertises only
|
|
6
|
+
* the tools it includes; instructions are trimmed to match so the agent
|
|
7
|
+
* doesn't hallucinate tools that aren't in tools/list.
|
|
8
|
+
*
|
|
9
|
+
* minimal — 5 core tools, minimal context overhead
|
|
10
|
+
* nav — 10 exploration tools, no editing
|
|
11
|
+
* edit — nav + 6 edit-prep tools (DEFAULT)
|
|
12
|
+
* full — everything including audit tools
|
|
13
|
+
*/
|
|
14
|
+
import type { ToolProfile } from "./tool-profiles.js";
|
|
15
|
+
/**
|
|
16
|
+
* Select MCP instructions for the given tool profile.
|
|
17
|
+
* Each profile only mentions tools that are actually advertised in its
|
|
18
|
+
* tools/list — prevents the agent from calling tools it can't see.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getMcpInstructions(profile: ToolProfile): string;
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated Use getMcpInstructions(profile) instead.
|
|
23
|
+
* Kept for backward-compat — resolves to the full profile instructions.
|
|
4
24
|
*/
|
|
5
25
|
export declare const MCP_INSTRUCTIONS: string;
|
|
6
26
|
export declare const TOOL_DEFINITIONS: ({
|