token-pilot 0.39.3 → 0.40.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- 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/typo-guard.d.ts +1 -1
- package/dist/cli/typo-guard.js +2 -0
- package/dist/hooks/installer.js +34 -5
- package/dist/hooks/subagent-stop.d.ts +55 -0
- package/dist/hooks/subagent-stop.js +108 -0
- package/dist/index.js +19 -0
- package/hooks/hooks.json +10 -0
- package/package.json +1 -1
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Token Pilot \u2014 save 60-90% tokens when AI reads code",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.40.0"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "token-pilot",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Reduces token consumption by 60-90% via AST-aware lazy file reading, structural symbol navigation, and cross-session tool-usage analytics. 22 MCP tools + 19 subagents + budget watchdog hooks.",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.40.0",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Digital-Threads"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "token-pilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "Saves 60-90% tokens on AI code reading. AST-aware lazy reads, symbol navigation, find_usages, structural git diff/log, edit-safety guard, Task-routing matcher, cross-session telemetry (errors + diagnostics), 25 tp-* subagents tiered to haiku/sonnet/opus with budget watchdog.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Digital-Threads",
|
|
@@ -9,7 +9,7 @@ tools:
|
|
|
9
9
|
- mcp__token-pilot__read_symbol
|
|
10
10
|
- Bash
|
|
11
11
|
model: haiku
|
|
12
|
-
token_pilot_version: "0.
|
|
12
|
+
token_pilot_version: "0.40.0"
|
|
13
13
|
token_pilot_body_hash: dd184501203fa7f3c73f419c4ffbe33c4be75400cb64a7a51733a3fe23f6e085
|
|
14
14
|
requiredMcpServers:
|
|
15
15
|
- "token-pilot"
|
|
@@ -8,7 +8,7 @@ tools:
|
|
|
8
8
|
- mcp__token-pilot__test_summary
|
|
9
9
|
- mcp__token-pilot__outline
|
|
10
10
|
- Bash
|
|
11
|
-
token_pilot_version: "0.
|
|
11
|
+
token_pilot_version: "0.40.0"
|
|
12
12
|
token_pilot_body_hash: de64a406b5176de19f7422619c7de7949b1f28865f225402c9cea9255f377428
|
|
13
13
|
requiredMcpServers:
|
|
14
14
|
- "token-pilot"
|
package/agents/tp-debugger.md
CHANGED
package/agents/tp-dep-health.md
CHANGED
package/agents/tp-doc-writer.md
CHANGED
|
@@ -12,7 +12,7 @@ tools:
|
|
|
12
12
|
- mcp__token-pilot__read_symbols
|
|
13
13
|
- Read
|
|
14
14
|
model: sonnet
|
|
15
|
-
token_pilot_version: "0.
|
|
15
|
+
token_pilot_version: "0.40.0"
|
|
16
16
|
token_pilot_body_hash: 351a987e11eba63852f5431a16d8eb53104f4f689f82fdcc5a2bf4db948ba92f
|
|
17
17
|
requiredMcpServers:
|
|
18
18
|
- "token-pilot"
|
|
@@ -8,7 +8,7 @@ tools:
|
|
|
8
8
|
- mcp__token-pilot__read_symbol
|
|
9
9
|
- Bash
|
|
10
10
|
model: inherit
|
|
11
|
-
token_pilot_version: "0.
|
|
11
|
+
token_pilot_version: "0.40.0"
|
|
12
12
|
token_pilot_body_hash: de5722bfea374eaab096c1ae635c37879e7a91370ee3cd0532f4240be03c91eb
|
|
13
13
|
requiredMcpServers:
|
|
14
14
|
- "token-pilot"
|
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.40.0"
|
|
14
14
|
token_pilot_body_hash: 832e95633fbc8e9b0c10f3e540a327d4be062fb4b3f17a6cce6be13f414e2927
|
|
15
15
|
requiredMcpServers:
|
|
16
16
|
- "token-pilot"
|
package/agents/tp-pr-reviewer.md
CHANGED
|
@@ -11,7 +11,7 @@ tools:
|
|
|
11
11
|
- mcp__token-pilot__read_for_edit
|
|
12
12
|
- Read
|
|
13
13
|
model: sonnet
|
|
14
|
-
token_pilot_version: "0.
|
|
14
|
+
token_pilot_version: "0.40.0"
|
|
15
15
|
token_pilot_body_hash: f83f50d05b4f70285ae7afed2b1a406fc436df56e61a0aedbfb31edc7f2b6e66
|
|
16
16
|
requiredMcpServers:
|
|
17
17
|
- "token-pilot"
|
|
@@ -8,7 +8,7 @@ tools:
|
|
|
8
8
|
- mcp__token-pilot__outline
|
|
9
9
|
- mcp__token-pilot__read_symbol
|
|
10
10
|
model: sonnet
|
|
11
|
-
token_pilot_version: "0.
|
|
11
|
+
token_pilot_version: "0.40.0"
|
|
12
12
|
token_pilot_body_hash: c5f6fc122c89e16e5cf774045f92169ee3468555320b898171ba13eca5323550
|
|
13
13
|
requiredMcpServers:
|
|
14
14
|
- "token-pilot"
|
|
@@ -9,7 +9,7 @@ tools:
|
|
|
9
9
|
- mcp__token-pilot__module_info
|
|
10
10
|
- Bash
|
|
11
11
|
model: sonnet
|
|
12
|
-
token_pilot_version: "0.
|
|
12
|
+
token_pilot_version: "0.40.0"
|
|
13
13
|
token_pilot_body_hash: 8ef3c3341cbfed4eb8dd130126a9683edc57e378c92ff0ca764d584fd941c55c
|
|
14
14
|
requiredMcpServers:
|
|
15
15
|
- "token-pilot"
|
package/agents/tp-run.md
CHANGED
package/agents/tp-spec-writer.md
CHANGED
|
@@ -10,7 +10,7 @@ tools:
|
|
|
10
10
|
- mcp__token-pilot__test_summary
|
|
11
11
|
- Glob
|
|
12
12
|
- Grep
|
|
13
|
-
token_pilot_version: "0.
|
|
13
|
+
token_pilot_version: "0.40.0"
|
|
14
14
|
token_pilot_body_hash: be81eed53a3720d146cf89e4a14a7a56577633f7c84c234c412ab70d64c05b11
|
|
15
15
|
requiredMcpServers:
|
|
16
16
|
- "token-pilot"
|
package/agents/tp-test-triage.md
CHANGED
|
@@ -8,7 +8,7 @@ tools:
|
|
|
8
8
|
- mcp__token-pilot__find_usages
|
|
9
9
|
- mcp__token-pilot__read_symbol
|
|
10
10
|
model: sonnet
|
|
11
|
-
token_pilot_version: "0.
|
|
11
|
+
token_pilot_version: "0.40.0"
|
|
12
12
|
token_pilot_body_hash: 362ecf4cb03b059421ea26933473700900073dc38b3a7fe271208dfb1ae14f90
|
|
13
13
|
requiredMcpServers:
|
|
14
14
|
- "token-pilot"
|
package/agents/tp-test-writer.md
CHANGED
package/dist/cli/typo-guard.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Everything else passes through untouched — a real project root like
|
|
18
18
|
* `/home/user/my-project` or `./subdir` goes to startServer as before.
|
|
19
19
|
*/
|
|
20
|
-
export declare const KNOWN_COMMANDS: readonly ["hook-read", "hook-edit", "hook-pre-bash", "hook-pre-grep", "hook-pre-task", "hook-post-bash", "hook-post-task", "hook-session-start", "hook-bootstrap", "install-hook", "uninstall-hook", "install-ast-index", "doctor", "bless-agents", "unbless-agents", "install-agents", "uninstall-agents", "stats", "tool-audit", "save-doc", "list-docs", "init", "migrate-hooks", "errors", "workflow", "--version", "-v", "--help", "-h"];
|
|
20
|
+
export declare const KNOWN_COMMANDS: readonly ["hook-read", "hook-edit", "hook-pre-bash", "hook-pre-grep", "hook-pre-task", "hook-post-bash", "hook-post-task", "hook-session-start", "hook-bootstrap", "hook-subagent-stop", "install-hook", "uninstall-hook", "install-ast-index", "doctor", "bless-agents", "unbless-agents", "install-agents", "uninstall-agents", "stats", "tool-audit", "save-doc", "list-docs", "init", "migrate-hooks", "errors", "workflow", "--version", "-v", "--help", "-h"];
|
|
21
21
|
export interface TypoGuardResult {
|
|
22
22
|
kind: "pass-through" | "typo";
|
|
23
23
|
suggestion?: string;
|
package/dist/cli/typo-guard.js
CHANGED
|
@@ -35,6 +35,8 @@ export const KNOWN_COMMANDS = [
|
|
|
35
35
|
// v0.35.0 — one-shot project setup hook (uses Claude Code's
|
|
36
36
|
// undocumented `once: true` SessionStart flag).
|
|
37
37
|
"hook-bootstrap",
|
|
38
|
+
// v0.40.0 — canonical subagent-completion capture
|
|
39
|
+
"hook-subagent-stop",
|
|
38
40
|
"install-hook",
|
|
39
41
|
"uninstall-hook",
|
|
40
42
|
"install-ast-index",
|
package/dist/hooks/installer.js
CHANGED
|
@@ -140,13 +140,21 @@ function createHookConfig(options) {
|
|
|
140
140
|
// v0.39.2 — post-task MUST run synchronously. It writes the
|
|
141
141
|
// `event:"task"` record via appendEvent (mkdir + stat +
|
|
142
142
|
// appendFile). Under `async: true` Claude Code fires the hook
|
|
143
|
-
// detached and may reap the process before those writes flush
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
// Telemetry integrity > the ~5ms saved on a non-hot-path hook.
|
|
143
|
+
// detached and may reap the process before those writes flush.
|
|
144
|
+
// Kept as a secondary path; v0.39.3 probe showed it does not
|
|
145
|
+
// fire on current Claude Code (see SubagentStop below).
|
|
147
146
|
hooks: [hookEntry("hook-post-task", options)],
|
|
148
147
|
},
|
|
149
148
|
],
|
|
149
|
+
// v0.40.0 — SubagentStop is the canonical, reliably-firing
|
|
150
|
+
// subagent-completion event. PostToolUse:Task proved non-firing
|
|
151
|
+
// for the dispatch tool; SubagentStop is where the task adoption
|
|
152
|
+
// signal is actually captured. Synchronous (writes telemetry).
|
|
153
|
+
SubagentStop: [
|
|
154
|
+
{
|
|
155
|
+
hooks: [hookEntry("hook-subagent-stop", options)],
|
|
156
|
+
},
|
|
157
|
+
],
|
|
150
158
|
},
|
|
151
159
|
};
|
|
152
160
|
}
|
|
@@ -276,6 +284,17 @@ export async function installHook(projectRoot, options) {
|
|
|
276
284
|
settings.hooks.PostToolUse.push(hookDef);
|
|
277
285
|
}
|
|
278
286
|
}
|
|
287
|
+
// v0.40.0 — SubagentStop (canonical subagent-completion capture).
|
|
288
|
+
// Installed idempotently, same pattern as SessionStart.
|
|
289
|
+
if (Array.isArray(hookConfig.hooks.SubagentStop)) {
|
|
290
|
+
if (!Array.isArray(settings.hooks.SubagentStop)) {
|
|
291
|
+
settings.hooks.SubagentStop = [];
|
|
292
|
+
}
|
|
293
|
+
const hasSubagentStop = settings.hooks.SubagentStop.some(isTokenPilotHook);
|
|
294
|
+
if (!hasSubagentStop) {
|
|
295
|
+
settings.hooks.SubagentStop.push(...hookConfig.hooks.SubagentStop);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
279
298
|
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
280
299
|
return {
|
|
281
300
|
installed: true,
|
|
@@ -303,7 +322,11 @@ export async function uninstallHook(projectRoot) {
|
|
|
303
322
|
const hasPreToolUse = !!settings.hooks?.PreToolUse;
|
|
304
323
|
const hasSessionStart = !!settings.hooks?.SessionStart;
|
|
305
324
|
const hasPostToolUse = !!settings.hooks?.PostToolUse;
|
|
306
|
-
|
|
325
|
+
const hasSubagentStop = !!settings.hooks?.SubagentStop;
|
|
326
|
+
if (!hasPreToolUse &&
|
|
327
|
+
!hasSessionStart &&
|
|
328
|
+
!hasPostToolUse &&
|
|
329
|
+
!hasSubagentStop) {
|
|
307
330
|
return { removed: false, fatal: false, message: "No hooks to remove." };
|
|
308
331
|
}
|
|
309
332
|
const isTokenPilotHook = (h) => h.hooks?.some((hook) => hook.command?.includes("token-pilot"));
|
|
@@ -325,6 +348,12 @@ export async function uninstallHook(projectRoot) {
|
|
|
325
348
|
delete settings.hooks.PostToolUse;
|
|
326
349
|
}
|
|
327
350
|
}
|
|
351
|
+
if (Array.isArray(settings.hooks?.SubagentStop)) {
|
|
352
|
+
settings.hooks.SubagentStop = settings.hooks.SubagentStop.filter((h) => !isTokenPilotHook(h));
|
|
353
|
+
if (settings.hooks.SubagentStop.length === 0) {
|
|
354
|
+
delete settings.hooks.SubagentStop;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
328
357
|
if (settings.hooks && Object.keys(settings.hooks).length === 0) {
|
|
329
358
|
delete settings.hooks;
|
|
330
359
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.40.0 — SubagentStop task-completion capture.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists (grounded, not speculative):
|
|
5
|
+
*
|
|
6
|
+
* PostToolUse:Task was supposed to record one `event:"task"` per
|
|
7
|
+
* subagent dispatch. A clean restarted-session probe on v0.39.3
|
|
8
|
+
* proved it does not fire: a real subagent dispatch produced ZERO
|
|
9
|
+
* events, while a Read-deny in the SAME session wrote its `denied`
|
|
10
|
+
* event fine (so appendEvent + the hook runtime are healthy). That
|
|
11
|
+
* is years of "0 task events" explained — the parent-side PostToolUse
|
|
12
|
+
* hook simply never lands for the dispatch tool on this Claude Code.
|
|
13
|
+
*
|
|
14
|
+
* SubagentStop is Claude Code's canonical subagent-completion event
|
|
15
|
+
* (confirmed in the 2.1.131/2.1.161 bundle schema:
|
|
16
|
+
* literal("SubagentStop"), stop_hook_active, agent_id,
|
|
17
|
+
* agent_transcript_path, agent_type, last_assistant_message ).
|
|
18
|
+
* It fires once per subagent completion by definition, so it is the
|
|
19
|
+
* reliable place to record the adoption signal the whole v0.30 goal
|
|
20
|
+
* depends on: WAS a subagent used, and was it a tp-* or not.
|
|
21
|
+
*
|
|
22
|
+
* Tokens: SubagentStop carries `agent_transcript_path`. We make a
|
|
23
|
+
* best-effort read of the transcript's cumulative usage; on any
|
|
24
|
+
* failure we record estTokens:0 — the agent_type signal is the
|
|
25
|
+
* primary value, tokens are secondary.
|
|
26
|
+
*
|
|
27
|
+
* Routing-miss detection (was general-purpose picked where a tp-*
|
|
28
|
+
* fit?) stays in the PreToolUse:Task diagnostic, which has the task
|
|
29
|
+
* description SubagentStop lacks. This hook records the ACTUAL
|
|
30
|
+
* completion; pre-task records the ADVICE.
|
|
31
|
+
*/
|
|
32
|
+
import type { HookEvent } from "../core/event-log.js";
|
|
33
|
+
export interface SubagentStopInput {
|
|
34
|
+
hook_event_name?: string;
|
|
35
|
+
agent_id?: string;
|
|
36
|
+
agent_type?: string;
|
|
37
|
+
agent_transcript_path?: string;
|
|
38
|
+
last_assistant_message?: string;
|
|
39
|
+
session_id?: string;
|
|
40
|
+
parent_agent_id?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Best-effort token total from a subagent transcript (JSONL of CC
|
|
44
|
+
* messages). Sums `usage.output_tokens` across assistant messages, or
|
|
45
|
+
* takes a cumulative `usage.total_tokens` when present. Returns 0 on
|
|
46
|
+
* any read/parse failure — never throws.
|
|
47
|
+
*/
|
|
48
|
+
export declare function tokensFromTranscript(path: string | undefined): number;
|
|
49
|
+
/**
|
|
50
|
+
* Build the `event:"task"` record from a SubagentStop payload. Pure —
|
|
51
|
+
* no I/O except the optional transcript token read, which the caller
|
|
52
|
+
* can pre-resolve for tests via `tokensOverride`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildSubagentTaskEvent(input: SubagentStopInput, now: number, tokensOverride?: number): HookEvent | null;
|
|
55
|
+
//# sourceMappingURL=subagent-stop.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.40.0 — SubagentStop task-completion capture.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists (grounded, not speculative):
|
|
5
|
+
*
|
|
6
|
+
* PostToolUse:Task was supposed to record one `event:"task"` per
|
|
7
|
+
* subagent dispatch. A clean restarted-session probe on v0.39.3
|
|
8
|
+
* proved it does not fire: a real subagent dispatch produced ZERO
|
|
9
|
+
* events, while a Read-deny in the SAME session wrote its `denied`
|
|
10
|
+
* event fine (so appendEvent + the hook runtime are healthy). That
|
|
11
|
+
* is years of "0 task events" explained — the parent-side PostToolUse
|
|
12
|
+
* hook simply never lands for the dispatch tool on this Claude Code.
|
|
13
|
+
*
|
|
14
|
+
* SubagentStop is Claude Code's canonical subagent-completion event
|
|
15
|
+
* (confirmed in the 2.1.131/2.1.161 bundle schema:
|
|
16
|
+
* literal("SubagentStop"), stop_hook_active, agent_id,
|
|
17
|
+
* agent_transcript_path, agent_type, last_assistant_message ).
|
|
18
|
+
* It fires once per subagent completion by definition, so it is the
|
|
19
|
+
* reliable place to record the adoption signal the whole v0.30 goal
|
|
20
|
+
* depends on: WAS a subagent used, and was it a tp-* or not.
|
|
21
|
+
*
|
|
22
|
+
* Tokens: SubagentStop carries `agent_transcript_path`. We make a
|
|
23
|
+
* best-effort read of the transcript's cumulative usage; on any
|
|
24
|
+
* failure we record estTokens:0 — the agent_type signal is the
|
|
25
|
+
* primary value, tokens are secondary.
|
|
26
|
+
*
|
|
27
|
+
* Routing-miss detection (was general-purpose picked where a tp-*
|
|
28
|
+
* fit?) stays in the PreToolUse:Task diagnostic, which has the task
|
|
29
|
+
* description SubagentStop lacks. This hook records the ACTUAL
|
|
30
|
+
* completion; pre-task records the ADVICE.
|
|
31
|
+
*/
|
|
32
|
+
import { readFileSync } from "node:fs";
|
|
33
|
+
/**
|
|
34
|
+
* Best-effort token total from a subagent transcript (JSONL of CC
|
|
35
|
+
* messages). Sums `usage.output_tokens` across assistant messages, or
|
|
36
|
+
* takes a cumulative `usage.total_tokens` when present. Returns 0 on
|
|
37
|
+
* any read/parse failure — never throws.
|
|
38
|
+
*/
|
|
39
|
+
export function tokensFromTranscript(path) {
|
|
40
|
+
if (!path || typeof path !== "string")
|
|
41
|
+
return 0;
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = readFileSync(path, "utf-8");
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
let out = 0;
|
|
50
|
+
let lastTotal = 0;
|
|
51
|
+
for (const line of raw.split("\n")) {
|
|
52
|
+
if (!line.trim())
|
|
53
|
+
continue;
|
|
54
|
+
let rec;
|
|
55
|
+
try {
|
|
56
|
+
rec = JSON.parse(line);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const msg = rec
|
|
62
|
+
.message;
|
|
63
|
+
const usage = msg?.usage ?? rec.usage;
|
|
64
|
+
if (usage && typeof usage === "object") {
|
|
65
|
+
const o = usage.output_tokens;
|
|
66
|
+
if (typeof o === "number")
|
|
67
|
+
out += o;
|
|
68
|
+
const t = usage.total_tokens;
|
|
69
|
+
if (typeof t === "number")
|
|
70
|
+
lastTotal = t;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Prefer summed output tokens; fall back to the last cumulative total.
|
|
74
|
+
return out > 0 ? out : lastTotal;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the `event:"task"` record from a SubagentStop payload. Pure —
|
|
78
|
+
* no I/O except the optional transcript token read, which the caller
|
|
79
|
+
* can pre-resolve for tests via `tokensOverride`.
|
|
80
|
+
*/
|
|
81
|
+
export function buildSubagentTaskEvent(input, now, tokensOverride) {
|
|
82
|
+
const agentType = typeof input.agent_type === "string" ? input.agent_type : "";
|
|
83
|
+
// No agent_type → nothing meaningful to record.
|
|
84
|
+
if (!agentType)
|
|
85
|
+
return null;
|
|
86
|
+
const est = tokensOverride ?? tokensFromTranscript(input.agent_transcript_path);
|
|
87
|
+
return {
|
|
88
|
+
ts: now,
|
|
89
|
+
session_id: input.session_id ?? "",
|
|
90
|
+
agent_type: input.agent_type ?? null,
|
|
91
|
+
agent_id: input.agent_id ?? null,
|
|
92
|
+
...(input.parent_agent_id ? { parent_agent_id: input.parent_agent_id } : {}),
|
|
93
|
+
event: "task",
|
|
94
|
+
file: "",
|
|
95
|
+
lines: 0,
|
|
96
|
+
estTokens: est,
|
|
97
|
+
summaryTokens: 0,
|
|
98
|
+
savedTokens: 0,
|
|
99
|
+
subagent_type: agentType,
|
|
100
|
+
// SubagentStop has no task description, so no heuristic match here.
|
|
101
|
+
// Routing-miss detection lives in the PreToolUse:Task diagnostic.
|
|
102
|
+
matched_tp_agent: null,
|
|
103
|
+
// Mark the source so a future revival of PostToolUse:Task can be
|
|
104
|
+
// deduped in stats rather than double-counted.
|
|
105
|
+
code: "subagent_stop",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=subagent-stop.js.map
|
package/dist/index.js
CHANGED
|
@@ -326,6 +326,25 @@ export async function main(cliArgs = process.argv.slice(2)) {
|
|
|
326
326
|
});
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
|
+
case "hook-subagent-stop": {
|
|
330
|
+
// v0.40.0 — canonical subagent-completion capture. PostToolUse:Task
|
|
331
|
+
// proved non-firing for the dispatch tool (clean v0.39.3 probe:
|
|
332
|
+
// a real dispatch wrote 0 events while a Read-deny in the same
|
|
333
|
+
// session wrote fine). SubagentStop fires once per subagent by
|
|
334
|
+
// definition, so this is the reliable source for the task
|
|
335
|
+
// adoption signal. Synchronous (writes telemetry — never async).
|
|
336
|
+
await runHookEntryPoint({ hook: "hook-subagent-stop" }, async () => {
|
|
337
|
+
const stdin = readFileSync(0, "utf-8");
|
|
338
|
+
const input = JSON.parse(stdin);
|
|
339
|
+
const { buildSubagentTaskEvent } = await import("./hooks/subagent-stop.js");
|
|
340
|
+
const ev = buildSubagentTaskEvent(input, Date.now());
|
|
341
|
+
if (ev) {
|
|
342
|
+
const { appendEvent } = await import("./core/event-log.js");
|
|
343
|
+
await appendEvent(process.cwd(), ev);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
329
348
|
case "hook-session-start": {
|
|
330
349
|
await runHookEntryPoint({ hook: "hook-session-start" }, async () => {
|
|
331
350
|
const cfg = await loadConfig(process.cwd());
|
package/hooks/hooks.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "token-pilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.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",
|