token-pilot 0.42.3 → 0.43.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.
Files changed (44) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/.claude-plugin/plugin.json +4 -2
  3. package/CHANGELOG.md +109 -0
  4. package/README.md +1 -1
  5. package/agents/tp-api-surface-tracker.md +1 -1
  6. package/agents/tp-audit-scanner.md +1 -1
  7. package/agents/tp-commit-writer.md +1 -1
  8. package/agents/tp-context-engineer.md +1 -1
  9. package/agents/tp-dead-code-finder.md +1 -1
  10. package/agents/tp-debugger.md +1 -1
  11. package/agents/tp-dep-health.md +1 -1
  12. package/agents/tp-doc-writer.md +1 -1
  13. package/agents/tp-history-explorer.md +1 -1
  14. package/agents/tp-impact-analyzer.md +1 -1
  15. package/agents/tp-incident-timeline.md +1 -1
  16. package/agents/tp-incremental-builder.md +1 -1
  17. package/agents/tp-migration-scout.md +1 -1
  18. package/agents/tp-onboard.md +1 -1
  19. package/agents/tp-performance-profiler.md +1 -1
  20. package/agents/tp-pr-reviewer.md +1 -1
  21. package/agents/tp-refactor-planner.md +1 -1
  22. package/agents/tp-review-impact.md +1 -1
  23. package/agents/tp-run.md +1 -1
  24. package/agents/tp-session-restorer.md +1 -1
  25. package/agents/tp-ship-coordinator.md +1 -1
  26. package/agents/tp-spec-writer.md +1 -1
  27. package/agents/tp-test-coverage-gapper.md +1 -1
  28. package/agents/tp-test-triage.md +1 -1
  29. package/agents/tp-test-writer.md +1 -1
  30. package/dist/ast-index/client.d.ts +16 -0
  31. package/dist/ast-index/client.js +30 -0
  32. package/dist/core/validation.d.ts +17 -0
  33. package/dist/core/validation.js +54 -0
  34. package/dist/handlers/module-route.d.ts +20 -0
  35. package/dist/handlers/module-route.js +73 -0
  36. package/dist/index.js +3 -3
  37. package/dist/server/tool-definitions.d.ts +250 -0
  38. package/dist/server/tool-definitions.js +40 -0
  39. package/dist/server.js +42 -2
  40. package/docs/tools.md +2 -1
  41. package/package.json +2 -2
  42. package/skills/guide/SKILL.md +4 -0
  43. package/skills/install/SKILL.md +4 -0
  44. package/skills/stats/SKILL.md +3 -0
@@ -5,15 +5,15 @@
5
5
  "email": "shahinyanm@gmail.com"
6
6
  },
7
7
  "metadata": {
8
- "description": "Token Pilot \u2014 save 60-90% tokens when AI reads code",
9
- "version": "0.42.3"
8
+ "description": "Token Pilot save 60-90% tokens when AI reads code",
9
+ "version": "0.43.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "token-pilot",
14
14
  "source": "./",
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.42.3",
15
+ "description": "Reduces token consumption by 60-90% via AST-aware lazy file reading, structural symbol navigation, and cross-session tool-usage analytics. 23 MCP tools + 25 subagents + budget watchdog hooks.",
16
+ "version": "0.43.1",
17
17
  "author": {
18
18
  "name": "Digital-Threads"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-pilot",
3
- "version": "0.42.3",
3
+ "version": "0.43.1",
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",
@@ -21,7 +21,9 @@
21
21
  "mcpServers": {
22
22
  "token-pilot": {
23
23
  "command": "sh",
24
- "args": ["${CLAUDE_PLUGIN_ROOT}/start.sh"]
24
+ "args": [
25
+ "${CLAUDE_PLUGIN_ROOT}/start.sh"
26
+ ]
25
27
  }
26
28
  }
27
29
  }
package/CHANGELOG.md CHANGED
@@ -5,6 +5,115 @@ 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.43.1] - 2026-06-06
9
+
10
+ ### Fixed — `@ast-index/cli` floor raised to `^3.44.0`
11
+
12
+ `module_route` (0.43.0) needs the ast-index `module-route` command, which
13
+ exists only in ast-index 3.44+. The floor was `^3.38.0`, so an install
14
+ resolving ast-index below 3.44 would have `module_route` fail. No API change.
15
+
16
+ ## [0.43.0] - 2026-06-06
17
+
18
+ Bundled release: everything actionable from **ast-index 3.41→3.45** and
19
+ **Claude Code 2.1.163→2.1.167**, plus a statusline fix.
20
+
21
+ ### Added — `module_route` MCP tool (ast-index 3.44)
22
+
23
+ New tool wrapping ast-index's `module-route` command: the transitive
24
+ dependency path(s) between two modules. Answers "how does module A reach
25
+ module B through the import graph?", traces coupling, and can emit a
26
+ dependency diagram.
27
+
28
+ - `from` / `to` (required), plus `all`, `maxPaths` (≤200), `maxDepth`
29
+ (≤50), `viaKind` (`api`/`implementation`/`all`), `format`
30
+ (`text`/`json`/`mermaid`/`dot`).
31
+ - Machine formats (json/mermaid/dot) pass through clean — no header that
32
+ would corrupt a diagram/parse. Text format gets a `MODULE ROUTE: a → b`
33
+ header.
34
+ - Empty output explains both causes (modules unrelated **or** the
35
+ module-dependency graph isn't indexed — `ast-index rebuild`).
36
+ - Full-profile only (not in nav/edit/minimal sets) — a specialised
37
+ analysis tool, like the audit tools.
38
+ - `exec` already sets `AST_INDEX_WALK_UP=1`, so the route resolves from a
39
+ monorepo subdir without passing `--walk-up`.
40
+
41
+ ### Fixed — statusline now counts MCP-tool savings, not just hook denials
42
+
43
+ The badge summed only `hook-events.jsonl` (`savedTokens` from intercepted
44
+ raw `Read`/`Grep`). The larger share — savings from the MCP tools
45
+ themselves (`smart_read`, `outline`, `find_usages`, …) — lives in
46
+ `tool-calls.jsonl` and was **invisible** to the badge, so the displayed
47
+ figure undercounted real savings (often by an order of magnitude).
48
+
49
+ Two changes fix it:
50
+
51
+ - The MCP server now stamps every `tool-calls.jsonl` row with the real
52
+ Claude Code session id, read from `CLAUDE_CODE_SESSION_ID` (exported to
53
+ child processes; verified against the 2.1.167 bundle — the same value
54
+ the hooks receive and the statusline payload carries). Previously these
55
+ rows had an empty `session_id`, so they could not be attributed to a
56
+ session at all.
57
+ - The statusline sums **both** logs: `hook-events.jsonl` `savedTokens`
58
+ plus `tool-calls.jsonl` (`tokensWouldBe − tokensReturned`), each split
59
+ into the current session and the project total. Zero/negative deltas
60
+ (pass-throughs) are ignored.
61
+
62
+ ### Added — statusline Claude.ai rate limits (CC 2.1.80+)
63
+
64
+ The badge now appends `5h:42% 7d:13%` when the statusline payload carries
65
+ `rate_limits` (subscribers only, after the first API response). Schema
66
+ verified against the 2.1.167 bundle: `rate_limits.five_hour.used_percentage`
67
+ and `rate_limits.seven_day.used_percentage`. Unlike the cumulative token
68
+ total, these numbers move every turn — the badge finally shows something
69
+ live. Parsed with `sed` (no `jq` dependency) and whitelisted to digits.
70
+
71
+ ### Fixed — statusline bare `[TP]` in monorepos / subdirs / worktrees
72
+
73
+ The badge resolved the events log only at the exact `cwd` from the
74
+ payload. In a monorepo (or worktree, or any session `cd`'d into a
75
+ subpackage) the `.token-pilot/` dir is at the repo root, so the lookup
76
+ failed and rendered a bare `[TP]` with no token count. The script now
77
+ **walks up** to the nearest ancestor with `.token-pilot/` (bounded to 40
78
+ levels), the same way git finds `.git`.
79
+
80
+ ### Changed — statusline shows session + project savings (`s:12.3k · 172.6k`)
81
+
82
+ The badge now renders **both** the current session's saved tokens (the
83
+ number you watch climb during a run) and the cumulative project total,
84
+ e.g. `[TP s:12.3k · 172.6k]`. A fresh session that hasn't saved anything
85
+ yet falls back to the project total alone (never an empty badge after
86
+ first use). Numbers render with one decimal (`172.6k`, not `172k`) so a
87
+ single turn's ~100-token savings is visible on each render — whole-`k`
88
+ rounding previously made the figure look frozen.
89
+
90
+ ### Added — `effort: low` on the bundled skills (CC 2.1.16x)
91
+
92
+ `guide` / `install` / `stats` declare `effort: low` — they render static
93
+ output or run one CLI call, so they don't need a high-effort model.
94
+ Faster and cheaper when invoked.
95
+
96
+ ### Notes — Claude Code 2.1.16x integration (no code change required)
97
+
98
+ - **`additionalContext` no longer dropped on a failed tool call** — our
99
+ PreToolUse routing guidance now survives a failed call (we benefit
100
+ automatically).
101
+ - **`SubagentStop` input gained `background_tasks` / `session_crons`** —
102
+ available to our subagent-stop hook for future budget feedback.
103
+ - **Glob deny rules (`"*"` denies all tools)** — usable as a second
104
+ enforcement layer on top of our deny hooks for stricter TP adoption.
105
+
106
+ ### Deferred — `MessageDisplay` hook (researched, not shipped)
107
+
108
+ CC's new `MessageDisplay` hook transforms assistant text *as displayed*.
109
+ Deliberately NOT wired this release: (1) the output contract (the field
110
+ that returns replacement text) is not confirmable from the minified
111
+ 2.1.167 bundle — and our rule is never to ship an unverified CC field
112
+ beside working hooks; (2) it is display-only, so it saves no input or
113
+ output tokens (the text is already generated and already in context).
114
+ That is caveman's cosmetic-output domain, not token-pilot's input domain.
115
+ Revisit once a live MessageDisplay payload pins the contract.
116
+
8
117
  ## [0.30.0] - 2026-04-19
9
118
 
10
119
  ### Added — `minimal` profile (5 tools, near-zero overhead)
package/README.md CHANGED
@@ -43,7 +43,7 @@ Creates (or merges into) `.mcp.json` with `token-pilot` + [`context-mode`](https
43
43
 
44
44
  ## What You Get
45
45
 
46
- - **22 MCP tools** — structural reads, symbol search, git analysis, session analytics → [tools reference](docs/tools.md)
46
+ - **23 MCP tools** — structural reads, symbol search, git analysis, module routing, session analytics → [tools reference](docs/tools.md)
47
47
  - **PreToolUse hooks** — block heavy `Grep`/`Bash`/`Read` calls; redirect to efficient alternatives → [hooks & modes](docs/hooks.md)
48
48
  - **25 `tp-*` subagents** (Claude Code only) — MCP-first delegates with haiku/sonnet model tiers and budget enforcement → [agents reference](docs/agents.md)
49
49
  - **Tool profiles** — trim advertised `tools/list` to save ~2 k tokens per session → [profiles & config](docs/configuration.md)
@@ -9,7 +9,7 @@ tools:
9
9
  - mcp__token-pilot__read_symbol
10
10
  - Bash
11
11
  model: haiku
12
- token_pilot_version: "0.42.3"
12
+ token_pilot_version: "0.43.1"
13
13
  token_pilot_body_hash: dd184501203fa7f3c73f419c4ffbe33c4be75400cb64a7a51733a3fe23f6e085
14
14
  requiredMcpServers:
15
15
  - "token-pilot"
@@ -11,7 +11,7 @@ tools:
11
11
  - Grep
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.42.3"
14
+ token_pilot_version: "0.43.1"
15
15
  token_pilot_body_hash: d172f600bf32277ea6eb4cbbee4542ddd698a986dcd96997d33930561964569b
16
16
  requiredMcpServers:
17
17
  - "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.42.3"
11
+ token_pilot_version: "0.43.1"
12
12
  token_pilot_body_hash: de64a406b5176de19f7422619c7de7949b1f28865f225402c9cea9255f377428
13
13
  requiredMcpServers:
14
14
  - "token-pilot"
@@ -13,7 +13,7 @@ tools:
13
13
  - Edit
14
14
  - Glob
15
15
  model: sonnet
16
- token_pilot_version: "0.42.3"
16
+ token_pilot_version: "0.43.1"
17
17
  token_pilot_body_hash: 68b32af2dacd82ebe52c4eec93edb903d452688274c3065218270627c564d8b0
18
18
  requiredMcpServers:
19
19
  - "token-pilot"
@@ -11,7 +11,7 @@ tools:
11
11
  - Grep
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.42.3"
14
+ token_pilot_version: "0.43.1"
15
15
  token_pilot_body_hash: d9b7f5b7ae6f4ae21305c775361bcab097cc774370a6d976c093571d46d55021
16
16
  requiredMcpServers:
17
17
  - "token-pilot"
@@ -12,7 +12,7 @@ tools:
12
12
  - Read
13
13
  - Bash
14
14
  model: sonnet
15
- token_pilot_version: "0.42.3"
15
+ token_pilot_version: "0.43.1"
16
16
  token_pilot_body_hash: 052413de8d92377edcde6ae5c823f5378db304baccfa29e8866467f42553a500
17
17
  requiredMcpServers:
18
18
  - "token-pilot"
@@ -9,7 +9,7 @@ tools:
9
9
  - Bash
10
10
  - Read
11
11
  model: haiku
12
- token_pilot_version: "0.42.3"
12
+ token_pilot_version: "0.43.1"
13
13
  token_pilot_body_hash: e14dc57493d816f8c2e017963e2ef5f66bea50fd0b805a80e8a0d97c968427e7
14
14
  requiredMcpServers:
15
15
  - "token-pilot"
@@ -13,7 +13,7 @@ tools:
13
13
  - Edit
14
14
  - Glob
15
15
  model: haiku
16
- token_pilot_version: "0.42.3"
16
+ token_pilot_version: "0.43.1"
17
17
  token_pilot_body_hash: 57d741794ab40e31a7ac49c68ea39a9088f5827cdef866ce81bfca1b7c9180cf
18
18
  requiredMcpServers:
19
19
  - "token-pilot"
@@ -10,7 +10,7 @@ tools:
10
10
  - Bash
11
11
  - Read
12
12
  model: haiku
13
- token_pilot_version: "0.42.3"
13
+ token_pilot_version: "0.43.1"
14
14
  token_pilot_body_hash: 7b70fa76a60e3c58a1de4f56c32c0f166424137e203a0cf1c8654e7c9235d904
15
15
  requiredMcpServers:
16
16
  - "token-pilot"
@@ -12,7 +12,7 @@ tools:
12
12
  - mcp__token-pilot__read_symbols
13
13
  - Read
14
14
  model: sonnet
15
- token_pilot_version: "0.42.3"
15
+ token_pilot_version: "0.43.1"
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.42.3"
11
+ token_pilot_version: "0.43.1"
12
12
  token_pilot_body_hash: de5722bfea374eaab096c1ae635c37879e7a91370ee3cd0532f4240be03c91eb
13
13
  requiredMcpServers:
14
14
  - "token-pilot"
@@ -13,7 +13,7 @@ tools:
13
13
  - Edit
14
14
  - Bash
15
15
  model: sonnet
16
- token_pilot_version: "0.42.3"
16
+ token_pilot_version: "0.43.1"
17
17
  token_pilot_body_hash: 375a824d0d847bb5453ec594c7a62ad566ee7e4d92717b0473f771f1a0477c60
18
18
  requiredMcpServers:
19
19
  - "token-pilot"
@@ -11,7 +11,7 @@ tools:
11
11
  - Grep
12
12
  - Glob
13
13
  model: sonnet
14
- token_pilot_version: "0.42.3"
14
+ token_pilot_version: "0.43.1"
15
15
  token_pilot_body_hash: 0334de1bf99b431b65359637d125cda7c44c6f780eb92c57cc538715b1939536
16
16
  requiredMcpServers:
17
17
  - "token-pilot"
@@ -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.42.3"
13
+ token_pilot_version: "0.43.1"
14
14
  token_pilot_body_hash: 832e95633fbc8e9b0c10f3e540a327d4be062fb4b3f17a6cce6be13f414e2927
15
15
  requiredMcpServers:
16
16
  - "token-pilot"
@@ -11,7 +11,7 @@ tools:
11
11
  - Bash
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.42.3"
14
+ token_pilot_version: "0.43.1"
15
15
  token_pilot_body_hash: b61f06380d80798fa2e49d37bcba0653495bee04dd6bdbc1feff9a75607b0508
16
16
  requiredMcpServers:
17
17
  - "token-pilot"
@@ -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.42.3"
14
+ token_pilot_version: "0.43.1"
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.42.3"
11
+ token_pilot_version: "0.43.1"
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.42.3"
12
+ token_pilot_version: "0.43.1"
13
13
  token_pilot_body_hash: 8ef3c3341cbfed4eb8dd130126a9683edc57e378c92ff0ca764d584fd941c55c
14
14
  requiredMcpServers:
15
15
  - "token-pilot"
package/agents/tp-run.md CHANGED
@@ -16,7 +16,7 @@ tools:
16
16
  - Glob
17
17
  - Bash
18
18
  model: haiku
19
- token_pilot_version: "0.42.3"
19
+ token_pilot_version: "0.43.1"
20
20
  token_pilot_body_hash: 2b08618d34a61f00aafccbda9fed6d83243296dedb83440edbd2d5c28bb6dbc4
21
21
  requiredMcpServers:
22
22
  - "token-pilot"
@@ -9,7 +9,7 @@ tools:
9
9
  - mcp__token-pilot__session_budget
10
10
  - Bash
11
11
  - Read
12
- token_pilot_version: "0.42.3"
12
+ token_pilot_version: "0.43.1"
13
13
  token_pilot_body_hash: 529374ed728f5eed5b758b3be3da65624783c0bf0c1a253d7d661a843eb5f767
14
14
  requiredMcpServers:
15
15
  - "token-pilot"
@@ -11,7 +11,7 @@ tools:
11
11
  - Read
12
12
  - Grep
13
13
  model: sonnet
14
- token_pilot_version: "0.42.3"
14
+ token_pilot_version: "0.43.1"
15
15
  token_pilot_body_hash: a60f6ae110eb3138064bce074e8ba26fa0ce5f4659df1624a9d9d3646803391b
16
16
  requiredMcpServers:
17
17
  - "token-pilot"
@@ -9,7 +9,7 @@ tools:
9
9
  - Read
10
10
  - Write
11
11
  model: sonnet
12
- token_pilot_version: "0.42.3"
12
+ token_pilot_version: "0.43.1"
13
13
  token_pilot_body_hash: c7a4e8b39228fd5158528f389c924c5ff2d98c4b9b05ee0106d54a26c5dc1350
14
14
  requiredMcpServers:
15
15
  - "token-pilot"
@@ -10,7 +10,7 @@ tools:
10
10
  - mcp__token-pilot__test_summary
11
11
  - Glob
12
12
  - Grep
13
- token_pilot_version: "0.42.3"
13
+ token_pilot_version: "0.43.1"
14
14
  token_pilot_body_hash: be81eed53a3720d146cf89e4a14a7a56577633f7c84c234c412ab70d64c05b11
15
15
  requiredMcpServers:
16
16
  - "token-pilot"
@@ -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.42.3"
11
+ token_pilot_version: "0.43.1"
12
12
  token_pilot_body_hash: 362ecf4cb03b059421ea26933473700900073dc38b3a7fe271208dfb1ae14f90
13
13
  requiredMcpServers:
14
14
  - "token-pilot"
@@ -13,7 +13,7 @@ tools:
13
13
  - Edit
14
14
  - Bash
15
15
  model: sonnet
16
- token_pilot_version: "0.42.3"
16
+ token_pilot_version: "0.43.1"
17
17
  token_pilot_body_hash: 269f2fe22ff4517c277d3f56ca67d8a5527b93290ab21079a83ba7af22c1b5a9
18
18
  requiredMcpServers:
19
19
  - "token-pilot"
@@ -80,6 +80,22 @@ export declare class AstIndexClient {
80
80
  stopPeriodicUpdate(): void;
81
81
  modules(pattern?: string): Promise<AstIndexModuleEntry[]>;
82
82
  moduleDeps(module: string): Promise<AstIndexModuleDep[]>;
83
+ /**
84
+ * Transitive dependency path(s) between two modules — ast-index 3.44
85
+ * `module-route`. Returns the raw CLI output for the requested format
86
+ * (text/json/mermaid/dot); the handler frames it. Null when the index
87
+ * is unavailable. `exec` already sets AST_INDEX_WALK_UP=1, so the
88
+ * `--walk-up` flag is implied and not passed here.
89
+ */
90
+ moduleRoute(opts: {
91
+ from: string;
92
+ to: string;
93
+ all?: boolean;
94
+ maxPaths?: number;
95
+ maxDepth?: number;
96
+ viaKind?: string;
97
+ format?: string;
98
+ }): Promise<string | null>;
83
99
  moduleDependents(module: string): Promise<AstIndexModuleDep[]>;
84
100
  unusedDeps(module: string): Promise<AstIndexUnusedDep[]>;
85
101
  moduleApi(module: string): Promise<AstIndexModuleApi[]>;
@@ -679,6 +679,36 @@ export class AstIndexClient {
679
679
  return [];
680
680
  }
681
681
  }
682
+ /**
683
+ * Transitive dependency path(s) between two modules — ast-index 3.44
684
+ * `module-route`. Returns the raw CLI output for the requested format
685
+ * (text/json/mermaid/dot); the handler frames it. Null when the index
686
+ * is unavailable. `exec` already sets AST_INDEX_WALK_UP=1, so the
687
+ * `--walk-up` flag is implied and not passed here.
688
+ */
689
+ async moduleRoute(opts) {
690
+ if (this.indexDisabled || this.indexOversized)
691
+ return null;
692
+ await this.ensureIndex();
693
+ try {
694
+ const cmdArgs = ["module-route", "--from", opts.from, "--to", opts.to];
695
+ if (opts.all)
696
+ cmdArgs.push("--all");
697
+ if (opts.maxPaths != null)
698
+ cmdArgs.push("--max-paths", String(opts.maxPaths));
699
+ if (opts.maxDepth != null)
700
+ cmdArgs.push("--max-depth", String(opts.maxDepth));
701
+ if (opts.viaKind)
702
+ cmdArgs.push("--via-kind", opts.viaKind);
703
+ if (opts.format)
704
+ cmdArgs.push("--format", opts.format);
705
+ return await this.exec(cmdArgs, 15000);
706
+ }
707
+ catch (err) {
708
+ console.error(`[token-pilot] ast-index module-route failed: ${err instanceof Error ? err.message : err}`);
709
+ return null;
710
+ }
711
+ }
682
712
  async moduleDependents(module) {
683
713
  if (this.indexDisabled || this.indexOversized)
684
714
  return [];
@@ -145,6 +145,23 @@ export interface ModuleInfoArgs {
145
145
  check?: "deps" | "dependents" | "api" | "unused-deps" | "all";
146
146
  }
147
147
  export declare function validateModuleInfoArgs(args: unknown): ModuleInfoArgs;
148
+ /**
149
+ * Validate module_route arguments.
150
+ *
151
+ * Wraps ast-index 3.44 `module-route` — the transitive dependency path
152
+ * between two modules. `from`/`to` are required; everything else mirrors
153
+ * the CLI flags with sane caps.
154
+ */
155
+ export interface ModuleRouteArgs {
156
+ from: string;
157
+ to: string;
158
+ all?: boolean;
159
+ maxPaths?: number;
160
+ maxDepth?: number;
161
+ viaKind?: "api" | "implementation" | "all";
162
+ format?: "text" | "json" | "mermaid" | "dot";
163
+ }
164
+ export declare function validateModuleRouteArgs(args: unknown): ModuleRouteArgs;
148
165
  /**
149
166
  * Validate smart_diff arguments.
150
167
  */
@@ -428,6 +428,60 @@ export function validateModuleInfoArgs(args) {
428
428
  check: check ?? "all",
429
429
  };
430
430
  }
431
+ export function validateModuleRouteArgs(args) {
432
+ if (!args || typeof args !== "object") {
433
+ throw new Error('Arguments must be an object with "from" and "to" parameters.');
434
+ }
435
+ const a = args;
436
+ if (typeof a.from !== "string" || a.from.length === 0) {
437
+ throw new Error('Required parameter "from" must be a non-empty string.');
438
+ }
439
+ if (typeof a.to !== "string" || a.to.length === 0) {
440
+ throw new Error('Required parameter "to" must be a non-empty string.');
441
+ }
442
+ let viaKind;
443
+ if (a.viaKind !== undefined && a.viaKind !== null) {
444
+ const valid = ["api", "implementation", "all"];
445
+ if (typeof a.viaKind !== "string" || !valid.includes(a.viaKind)) {
446
+ throw new Error(`"viaKind" must be one of: ${valid.join(", ")}`);
447
+ }
448
+ viaKind = a.viaKind;
449
+ }
450
+ let format;
451
+ if (a.format !== undefined && a.format !== null) {
452
+ const valid = ["text", "json", "mermaid", "dot"];
453
+ if (typeof a.format !== "string" || !valid.includes(a.format)) {
454
+ throw new Error(`"format" must be one of: ${valid.join(", ")}`);
455
+ }
456
+ format = a.format;
457
+ }
458
+ // Clamp numeric caps to safe ranges — never trust the caller blindly.
459
+ let maxPaths;
460
+ if (a.maxPaths !== undefined && a.maxPaths !== null) {
461
+ const n = Number(a.maxPaths);
462
+ if (!Number.isFinite(n) || n < 1) {
463
+ throw new Error('"maxPaths" must be a positive number.');
464
+ }
465
+ maxPaths = Math.min(Math.floor(n), 200);
466
+ }
467
+ let maxDepth;
468
+ if (a.maxDepth !== undefined && a.maxDepth !== null) {
469
+ const n = Number(a.maxDepth);
470
+ if (!Number.isFinite(n) || n < 1) {
471
+ throw new Error('"maxDepth" must be a positive number.');
472
+ }
473
+ maxDepth = Math.min(Math.floor(n), 50);
474
+ }
475
+ return {
476
+ from: a.from,
477
+ to: a.to,
478
+ all: a.all === true,
479
+ maxPaths,
480
+ maxDepth,
481
+ viaKind,
482
+ format,
483
+ };
484
+ }
431
485
  export function validateSmartDiffArgs(args) {
432
486
  if (!args || typeof args !== "object")
433
487
  return { scope: "unstaged" };
@@ -0,0 +1,20 @@
1
+ import type { AstIndexClient } from "../ast-index/client.js";
2
+ import type { ModuleRouteArgs } from "../core/validation.js";
3
+ /**
4
+ * module_route — transitive dependency path(s) between two modules.
5
+ *
6
+ * Thin wrapper over ast-index 3.44 `module-route`. The CLI already
7
+ * produces compact, purpose-built output (a path listing, or
8
+ * mermaid/dot/json for diagramming), so the handler only frames it and
9
+ * handles the empty / degraded cases — it does not re-parse the graph.
10
+ */
11
+ export declare function handleModuleRoute(args: ModuleRouteArgs, _projectRoot: string, astIndex: AstIndexClient): Promise<{
12
+ content: Array<{
13
+ type: "text";
14
+ text: string;
15
+ }>;
16
+ meta: {
17
+ files: string[];
18
+ };
19
+ }>;
20
+ //# sourceMappingURL=module-route.d.ts.map