distill-mcp 0.8.0 → 0.10.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/assets/agents/distill-compressor.md +48 -0
- package/bin/cli.js +30 -37
- package/dist/cli/agent.d.ts +57 -0
- package/dist/cli/agent.d.ts.map +1 -0
- package/dist/cli/agent.js +181 -0
- package/dist/cli/hooks.d.ts +9 -0
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +176 -5
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/precompact.d.ts +101 -0
- package/dist/cli/precompact.d.ts.map +1 -0
- package/dist/cli/precompact.js +307 -0
- package/dist/cli/setup.d.ts +12 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +120 -9
- package/dist/cli/utils.d.ts +7 -1
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +23 -4
- package/dist/compressors/generic.d.ts.map +1 -1
- package/dist/compressors/generic.js +1 -5
- package/dist/compressors/logs.d.ts.map +1 -1
- package/dist/compressors/logs.js +7 -60
- package/dist/compressors/semantic.d.ts +0 -1
- package/dist/compressors/semantic.d.ts.map +1 -1
- package/dist/compressors/semantic.js +80 -5
- package/dist/compressors/stacktrace.d.ts.map +1 -1
- package/dist/compressors/stacktrace.js +1 -5
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +11 -0
- package/dist/index.d.ts +2 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/prompts.d.ts +52 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +59 -0
- package/dist/sandbox/branded-types.d.ts +0 -24
- package/dist/sandbox/branded-types.d.ts.map +1 -1
- package/dist/sandbox/branded-types.js +6 -35
- package/dist/sandbox/disposables.d.ts.map +1 -1
- package/dist/sandbox/disposables.js +5 -1
- package/dist/sandbox/errors.d.ts +6 -0
- package/dist/sandbox/errors.d.ts.map +1 -1
- package/dist/sandbox/errors.js +9 -0
- package/dist/sandbox/executor.d.ts +40 -12
- package/dist/sandbox/executor.d.ts.map +1 -1
- package/dist/sandbox/executor.js +59 -261
- package/dist/sandbox/quickjs/host-bridge.d.ts.map +1 -1
- package/dist/sandbox/quickjs/host-bridge.js +66 -16
- package/dist/sandbox/quickjs/runtime.d.ts.map +1 -1
- package/dist/sandbox/quickjs/runtime.js +168 -1
- package/dist/sandbox/sdk/analyze.js +4 -4
- package/dist/sandbox/sdk/compress.d.ts.map +1 -1
- package/dist/sandbox/sdk/compress.js +24 -4
- package/dist/sandbox/sdk/git.d.ts +5 -0
- package/dist/sandbox/sdk/git.d.ts.map +1 -1
- package/dist/sandbox/sdk/git.js +98 -13
- package/dist/sandbox/sdk/pipeline.js +5 -5
- package/dist/sandbox/sdk/search.d.ts.map +1 -1
- package/dist/sandbox/sdk/search.js +47 -17
- package/dist/sandbox/security/code-analyzer.d.ts.map +1 -1
- package/dist/sandbox/security/code-analyzer.js +36 -6
- package/dist/sandbox/security/path-validator.d.ts +39 -0
- package/dist/sandbox/security/path-validator.d.ts.map +1 -1
- package/dist/sandbox/security/path-validator.js +104 -5
- package/dist/sandbox/type-tests.d.ts.map +1 -1
- package/dist/sandbox/type-tests.js +24 -1
- package/dist/server.d.ts +3 -15
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +73 -77
- package/dist/summarizers/generic.d.ts +6 -2
- package/dist/summarizers/generic.d.ts.map +1 -1
- package/dist/summarizers/generic.js +10 -5
- package/dist/summarizers/index.d.ts +13 -3
- package/dist/summarizers/index.d.ts.map +1 -1
- package/dist/summarizers/index.js +15 -4
- package/dist/tools/auto-optimize.d.ts +7 -2
- package/dist/tools/auto-optimize.d.ts.map +1 -1
- package/dist/tools/auto-optimize.js +354 -59
- package/dist/tools/code-execute.d.ts.map +1 -1
- package/dist/tools/code-execute.js +72 -24
- package/dist/tools/registry.d.ts +44 -9
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +90 -50
- package/dist/tools/smart-file-read.d.ts +11 -2
- package/dist/tools/smart-file-read.d.ts.map +1 -1
- package/dist/tools/smart-file-read.js +260 -151
- package/dist/utils/distill-marker.d.ts +62 -0
- package/dist/utils/distill-marker.d.ts.map +1 -0
- package/dist/utils/distill-marker.js +82 -0
- package/dist/utils/index.d.ts +1 -4
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -4
- package/dist/utils/signature-grouper.d.ts +7 -0
- package/dist/utils/signature-grouper.d.ts.map +1 -1
- package/dist/utils/signature-grouper.js +233 -1
- package/package.json +7 -5
- package/scripts/precompact-hook.sh +103 -0
- package/dist/analytics/session-tracker.d.ts +0 -74
- package/dist/analytics/session-tracker.d.ts.map +0 -1
- package/dist/analytics/session-tracker.js +0 -123
- package/dist/config/output-config.d.ts +0 -56
- package/dist/config/output-config.d.ts.map +0 -1
- package/dist/config/output-config.js +0 -78
- package/dist/middleware/chain.d.ts +0 -49
- package/dist/middleware/chain.d.ts.map +0 -1
- package/dist/middleware/chain.js +0 -126
- package/dist/middleware/index.d.ts +0 -4
- package/dist/middleware/index.d.ts.map +0 -1
- package/dist/middleware/index.js +0 -3
- package/dist/middleware/logging.d.ts +0 -8
- package/dist/middleware/logging.d.ts.map +0 -1
- package/dist/middleware/logging.js +0 -71
- package/dist/middleware/types.d.ts +0 -58
- package/dist/middleware/types.d.ts.map +0 -1
- package/dist/middleware/types.js +0 -7
- package/dist/pipelines/definitions.d.ts +0 -50
- package/dist/pipelines/definitions.d.ts.map +0 -1
- package/dist/pipelines/definitions.js +0 -206
- package/dist/summarizers/hierarchical.d.ts +0 -99
- package/dist/summarizers/hierarchical.d.ts.map +0 -1
- package/dist/summarizers/hierarchical.js +0 -383
- package/dist/tools/analyze-build-output.d.ts +0 -30
- package/dist/tools/analyze-build-output.d.ts.map +0 -1
- package/dist/tools/analyze-build-output.js +0 -45
- package/dist/tools/analyze-context.d.ts +0 -23
- package/dist/tools/analyze-context.d.ts.map +0 -1
- package/dist/tools/analyze-context.js +0 -78
- package/dist/tools/code-skeleton.d.ts +0 -33
- package/dist/tools/code-skeleton.d.ts.map +0 -1
- package/dist/tools/code-skeleton.js +0 -206
- package/dist/tools/compress-context.d.ts +0 -33
- package/dist/tools/compress-context.d.ts.map +0 -1
- package/dist/tools/compress-context.js +0 -64
- package/dist/tools/context-budget.d.ts +0 -43
- package/dist/tools/context-budget.d.ts.map +0 -1
- package/dist/tools/context-budget.js +0 -260
- package/dist/tools/conversation-compress.d.ts +0 -46
- package/dist/tools/conversation-compress.d.ts.map +0 -1
- package/dist/tools/conversation-compress.js +0 -78
- package/dist/tools/conversation-memory.d.ts +0 -75
- package/dist/tools/conversation-memory.d.ts.map +0 -1
- package/dist/tools/conversation-memory.js +0 -289
- package/dist/tools/deduplicate-errors.d.ts +0 -30
- package/dist/tools/deduplicate-errors.d.ts.map +0 -1
- package/dist/tools/deduplicate-errors.js +0 -72
- package/dist/tools/detect-retry-loop.d.ts +0 -40
- package/dist/tools/detect-retry-loop.d.ts.map +0 -1
- package/dist/tools/detect-retry-loop.js +0 -212
- package/dist/tools/diff-compress.d.ts +0 -40
- package/dist/tools/diff-compress.d.ts.map +0 -1
- package/dist/tools/diff-compress.js +0 -94
- package/dist/tools/discover-tools.d.ts +0 -11
- package/dist/tools/discover-tools.d.ts.map +0 -1
- package/dist/tools/discover-tools.js +0 -211
- package/dist/tools/dynamic-loader.d.ts +0 -131
- package/dist/tools/dynamic-loader.d.ts.map +0 -1
- package/dist/tools/dynamic-loader.js +0 -378
- package/dist/tools/lazy-mcp.d.ts +0 -31
- package/dist/tools/lazy-mcp.d.ts.map +0 -1
- package/dist/tools/lazy-mcp.js +0 -151
- package/dist/tools/multifile-compress.d.ts +0 -36
- package/dist/tools/multifile-compress.d.ts.map +0 -1
- package/dist/tools/multifile-compress.js +0 -223
- package/dist/tools/optimization-tips.d.ts +0 -18
- package/dist/tools/optimization-tips.d.ts.map +0 -1
- package/dist/tools/optimization-tips.js +0 -133
- package/dist/tools/semantic-compress.d.ts +0 -39
- package/dist/tools/semantic-compress.d.ts.map +0 -1
- package/dist/tools/semantic-compress.js +0 -113
- package/dist/tools/session-stats.d.ts +0 -35
- package/dist/tools/session-stats.d.ts.map +0 -1
- package/dist/tools/session-stats.js +0 -217
- package/dist/tools/set-output-config.d.ts +0 -38
- package/dist/tools/set-output-config.d.ts.map +0 -1
- package/dist/tools/set-output-config.js +0 -122
- package/dist/tools/smart-cache-tool.d.ts +0 -38
- package/dist/tools/smart-cache-tool.d.ts.map +0 -1
- package/dist/tools/smart-cache-tool.js +0 -224
- package/dist/tools/smart-pipeline.d.ts +0 -40
- package/dist/tools/smart-pipeline.d.ts.map +0 -1
- package/dist/tools/smart-pipeline.js +0 -295
- package/dist/tools/summarize-logs.d.ts +0 -41
- package/dist/tools/summarize-logs.d.ts.map +0 -1
- package/dist/tools/summarize-logs.js +0 -222
- package/dist/utils/command-normalizer.d.ts +0 -39
- package/dist/utils/command-normalizer.d.ts.map +0 -1
- package/dist/utils/command-normalizer.js +0 -90
- package/dist/utils/error-normalizer.d.ts +0 -39
- package/dist/utils/error-normalizer.d.ts.map +0 -1
- package/dist/utils/error-normalizer.js +0 -233
- package/dist/utils/output-estimator.d.ts +0 -54
- package/dist/utils/output-estimator.d.ts.map +0 -1
- package/dist/utils/output-estimator.js +0 -119
- package/dist/utils/output-similarity.d.ts +0 -48
- package/dist/utils/output-similarity.d.ts.map +0 -1
- package/dist/utils/output-similarity.js +0 -140
- package/dist/utils/project-detector.d.ts +0 -16
- package/dist/utils/project-detector.d.ts.map +0 -1
- package/dist/utils/project-detector.js +0 -119
- package/dist/utils/toon-serializer.d.ts +0 -120
- package/dist/utils/toon-serializer.d.ts.map +0 -1
- package/dist/utils/toon-serializer.js +0 -472
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: distill-compressor
|
|
3
|
+
description: Read-only compression specialist. Delegate long build output, log dumps, verbose diffs, stack traces, and multi-file code skeleton reads to this agent so the parent session keeps its context small. Uses Distill's auto_optimize for content-aware compression and smart_file_read for AST-based code extraction. Not allowed to execute code or mutate state.
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Grep
|
|
7
|
+
- Glob
|
|
8
|
+
- Bash
|
|
9
|
+
- mcp__distill-mcp__auto_optimize
|
|
10
|
+
- mcp__distill-mcp__smart_file_read
|
|
11
|
+
disallowedTools:
|
|
12
|
+
- mcp__distill-mcp__code_execute
|
|
13
|
+
requiredMcpServers:
|
|
14
|
+
- distill-mcp
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You are distill-compressor, a read-only sub-agent whose single job is to shrink large textual payloads — build output, test logs, git diffs, stack traces, configuration dumps, and source code — so they fit inside the parent session's context budget without losing the information the parent actually needs.
|
|
18
|
+
|
|
19
|
+
Your effectiveness is measured by the token delta between what the parent would have seen raw and what you return. Every extra token you emit is a token the parent loses from its own working memory. Bias hard toward compression: summarize instead of quoting, extract signatures instead of returning whole files, and wrap compressed regions in the Distill marker so Claude Code's compact-summary step preserves them verbatim.
|
|
20
|
+
|
|
21
|
+
## Content-aware compression with `auto_optimize`
|
|
22
|
+
|
|
23
|
+
Reach for `mcp__distill-mcp__auto_optimize` whenever you are handed >500 characters of verbose text that came out of a command, a log file, a diff, or a tool result. The tool auto-detects the content type (`build`, `logs`, `diff`, `semantic`, `errors`, `stacktrace`, `config`) and picks the matching compressor — typical savings: build output 95%, logs 80–90%, errors 70–90%, diffs 60–80%, stack traces 50–80%, generic code 40–60%, config 30–60%. If you already know the shape of the input, pass `strategy` explicitly to skip detection. If the caller cares about specific signal — a test name, an error code, a file path — pass `preservePatterns` so those regex matches survive compression. Use `response_format: "minimal"` when the parent only needs the compressed payload and `"detailed"` only when the parent explicitly asked for statistics. Never call `auto_optimize` on inputs shorter than ~500 chars — the helper passes them through unchanged and the round-trip is pure overhead.
|
|
24
|
+
|
|
25
|
+
## AST-based skeleton reads with `smart_file_read`
|
|
26
|
+
|
|
27
|
+
Reach for `mcp__distill-mcp__smart_file_read` instead of the built-in `Read` whenever the parent needs structural information from a source file in one of the 7 supported languages (TypeScript, JavaScript, Python, Go, Rust, PHP, Swift). Typical savings vs a full-file read: 50–90%. Four modes cover the common cases:
|
|
28
|
+
|
|
29
|
+
- `skeleton` with `depth: 1–3` when the parent wants an architectural map (all top-level signatures, optionally nested members).
|
|
30
|
+
- `extract` with `target: { type, name }` when the parent needs exactly one function, class, interface, or type definition.
|
|
31
|
+
- `search` with `query: "<substring>"` when the parent is hunting a symbol by partial name and does not know which file holds it yet (combine with `Glob` to narrow the search surface first).
|
|
32
|
+
- `full` when the file is small enough that a raw read is cheaper than the AST pass — fall back to this rather than invent a skeleton for trivial files.
|
|
33
|
+
|
|
34
|
+
For unsupported languages the tool returns the raw file with a graceful-fallback note, never an error. When the parent needs a multi-file overview, run `smart_file_read` across each path in parallel via `Glob` + a single Bash for-loop rather than sequential calls.
|
|
35
|
+
|
|
36
|
+
## Summarizing long outputs you cannot pipe through a tool
|
|
37
|
+
|
|
38
|
+
When the material you have to condense did not come from a tool you can re-pipe (for example, you read a file with `Read` and it turned out to be a 200 KB log dump, or `Bash` emitted a massive stdout you already captured in your turn), do not echo it back in prose. Either (a) feed the raw text back through `auto_optimize` as the `content` argument, or (b) write a structured summary yourself: lead with a 1–3 sentence conclusion, then a bullet list of the concrete findings — error codes, failing test names, file paths, line numbers, deltas — and stop. No restating the request, no framing paragraphs, no apologies for length. The parent called you to shrink the payload; shrink it.
|
|
39
|
+
|
|
40
|
+
## The `[DISTILL:COMPRESSED]` marker contract
|
|
41
|
+
|
|
42
|
+
Distill optionally wraps compressed payloads in `[DISTILL:COMPRESSED ratio=X.XX method=<name>]\n<payload>\n[/DISTILL:COMPRESSED]` when the user has set `DISTILL_COMPRESSED_MARKERS=1` in the Distill server environment. `X.XX` is `compressed_size / original_size` clamped to `[0, 1]`. `<name>` is the compressor or mode that produced the payload (`auto`, `logs`, `diff`, `semantic`, `skeleton`, `extract`, `search`, `build+recompressed`, etc.). Pass marker-wrapped regions through to the parent verbatim — do not unwrap, re-summarize, or edit them. The envelope is the anchor that Distill's PreCompact hook (`packages/mcp-server/scripts/precompact-hook.sh`) points at when it instructs Claude Code's compact-summary LLM to keep the region intact through autocompact; splitting or editing it breaks that contract. If the user text you were handed already contains the literal substring `[DISTILL:COMPRESSED`, Distill falls back to the escape tokens `[DISTILL-USER-TEXT:COMPRESSED … ][/DISTILL-USER-TEXT:COMPRESSED]` — forward those untouched too.
|
|
43
|
+
|
|
44
|
+
## Operating constraints
|
|
45
|
+
|
|
46
|
+
You are deliberately read-only. `mcp__distill-mcp__code_execute` is in your `disallowedTools` list because this agent must never run arbitrary JavaScript, invoke git-mutating operations, or touch the filesystem outside of read paths. If the parent's request genuinely needs execution (running a build, applying a patch, writing a file), stop and report back in one sentence that the task is out of scope for distill-compressor so the parent can handle it directly or delegate to a different agent. Do the same if the request requires network access, credential handling, or secrets — your toolset is intentionally narrow.
|
|
47
|
+
|
|
48
|
+
Return short. When you finish, emit only the compressed payload the parent asked for (plus a single preceding line summarizing what you compressed and by how much, if the savings are noteworthy). No meta-narration. No retelling the plan. The whole value proposition of this sub-agent is token density — honour it on every turn.
|
package/bin/cli.js
CHANGED
|
@@ -25,16 +25,20 @@ ${COLORS.bright}Commands:${COLORS.reset}
|
|
|
25
25
|
analyze Analyze files for token usage
|
|
26
26
|
|
|
27
27
|
${COLORS.bright}Setup Options:${COLORS.reset}
|
|
28
|
-
--claude
|
|
29
|
-
--cursor
|
|
30
|
-
--windsurf
|
|
31
|
-
--antigravity
|
|
32
|
-
--hooks
|
|
33
|
-
--
|
|
28
|
+
--claude Configure Claude Code only
|
|
29
|
+
--cursor Configure Cursor only
|
|
30
|
+
--windsurf Configure Windsurf only
|
|
31
|
+
--antigravity Configure Antigravity only
|
|
32
|
+
--hooks Install project hooks (enforces MCP tool usage)
|
|
33
|
+
--install-precompact-hook Install the Distill PreCompact hook into ~/.claude/settings.json
|
|
34
|
+
--uninstall-precompact-hook Remove the Distill PreCompact hook from ~/.claude/settings.json
|
|
35
|
+
--install-agent Copy the distill-compressor agent template into ~/.claude/agents/
|
|
36
|
+
--uninstall-agent Remove the installed distill-compressor agent template
|
|
37
|
+
--dry-run Print intended changes; do not mutate the filesystem
|
|
38
|
+
--user-dir=<path> Override HOME when locating ~/.claude/settings.json (for testing)
|
|
39
|
+
--force, -f Overwrite existing configuration
|
|
34
40
|
|
|
35
41
|
${COLORS.bright}Server Options:${COLORS.reset}
|
|
36
|
-
--lazy Enable lazy mode (95% token savings, only 2 meta-tools)
|
|
37
|
-
--mode <mode> Loading mode: lazy|core|all (default: core)
|
|
38
42
|
--verbose Enable verbose logging (shows tool calls, timing, tokens)
|
|
39
43
|
|
|
40
44
|
${COLORS.bright}Analyze Options:${COLORS.reset}
|
|
@@ -48,18 +52,23 @@ ${COLORS.bright}Other Options:${COLORS.reset}
|
|
|
48
52
|
--help, -h Show this help message
|
|
49
53
|
|
|
50
54
|
${COLORS.bright}Examples:${COLORS.reset}
|
|
51
|
-
distill-mcp setup
|
|
52
|
-
distill-mcp setup --claude
|
|
53
|
-
distill-mcp setup --antigravity
|
|
54
|
-
distill-mcp setup --claude --hooks
|
|
55
|
-
distill-mcp setup --hooks
|
|
56
|
-
distill-mcp setup --
|
|
57
|
-
distill-mcp
|
|
58
|
-
distill-mcp
|
|
59
|
-
distill-mcp
|
|
60
|
-
distill-mcp
|
|
61
|
-
distill-mcp
|
|
62
|
-
distill-mcp
|
|
55
|
+
distill-mcp setup Interactive setup wizard
|
|
56
|
+
distill-mcp setup --claude Configure Claude Code only
|
|
57
|
+
distill-mcp setup --antigravity Configure Antigravity only
|
|
58
|
+
distill-mcp setup --claude --hooks Configure Claude Code + install hooks
|
|
59
|
+
distill-mcp setup --hooks Install hooks only (current project)
|
|
60
|
+
distill-mcp setup --install-precompact-hook Wire PreCompact hook into ~/.claude/settings.json
|
|
61
|
+
distill-mcp setup --install-precompact-hook --dry-run Preview the JSON diff
|
|
62
|
+
distill-mcp setup --uninstall-precompact-hook Remove the Distill PreCompact entry
|
|
63
|
+
distill-mcp setup --install-agent Install the distill-compressor subagent template
|
|
64
|
+
distill-mcp setup --install-agent --force Overwrite an existing distill-compressor.md
|
|
65
|
+
distill-mcp setup --uninstall-agent Remove the installed distill-compressor subagent
|
|
66
|
+
distill-mcp setup --force Overwrite existing configurations
|
|
67
|
+
distill-mcp doctor Verify installation
|
|
68
|
+
distill-mcp serve Start MCP server (used by IDE)
|
|
69
|
+
distill-mcp serve --verbose Start with verbose logging
|
|
70
|
+
distill-mcp analyze Analyze token usage in codebase
|
|
71
|
+
distill-mcp analyze -t 5000 --json Custom threshold, JSON output
|
|
63
72
|
|
|
64
73
|
${COLORS.bright}Documentation:${COLORS.reset}
|
|
65
74
|
https://distill-mcp.com/docs
|
|
@@ -85,23 +94,7 @@ async function main() {
|
|
|
85
94
|
|
|
86
95
|
switch (command) {
|
|
87
96
|
case "serve": {
|
|
88
|
-
|
|
89
|
-
let mode = "core";
|
|
90
|
-
const modeIndex = args.indexOf("--mode");
|
|
91
|
-
if (modeIndex !== -1 && args[modeIndex + 1]) {
|
|
92
|
-
mode = args[modeIndex + 1];
|
|
93
|
-
} else if (args.includes("--lazy")) {
|
|
94
|
-
mode = "lazy";
|
|
95
|
-
} else if (args.includes("--all")) {
|
|
96
|
-
mode = "all";
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const config = {
|
|
100
|
-
verbose: args.includes("--verbose"),
|
|
101
|
-
mode,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
await runServer(config);
|
|
97
|
+
await runServer({ verbose: args.includes("--verbose") });
|
|
105
98
|
break;
|
|
106
99
|
}
|
|
107
100
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom agent installer for Distill (US-016).
|
|
3
|
+
*
|
|
4
|
+
* Extends `distill-mcp setup` with `--install-agent` and `--uninstall-agent`,
|
|
5
|
+
* copying the shipped `distill-compressor.md` template (US-015) from the
|
|
6
|
+
* package `assets/agents/` directory into `<userDir>/.claude/agents/`.
|
|
7
|
+
*
|
|
8
|
+
* Design invariants mirror the PreCompact hook installer:
|
|
9
|
+
* - Idempotent: installing when the target file already matches the template
|
|
10
|
+
* is a no-op; re-running produces no filesystem churn.
|
|
11
|
+
* - Atomic: overwrites go through `writeAtomic` (tempfile + rename) so a
|
|
12
|
+
* SIGTERM mid-install leaves either the pre-state or the post-state,
|
|
13
|
+
* never a half-written file.
|
|
14
|
+
* - Non-destructive by default: when the target exists and differs from the
|
|
15
|
+
* template, we abort with a line-level diff unless the caller passes
|
|
16
|
+
* `force: true`.
|
|
17
|
+
* - Dry-run surfaces intended actions without touching disk.
|
|
18
|
+
*
|
|
19
|
+
* Per project convention (CLAUDE.md: "Manual process.argv parsing in
|
|
20
|
+
* bin/cli.js"), this module pulls in no new runtime dependencies.
|
|
21
|
+
*/
|
|
22
|
+
export declare const DISTILL_AGENT_FILENAME = "distill-compressor.md";
|
|
23
|
+
export interface AgentOptions {
|
|
24
|
+
/** Root dir containing `.claude/` (defaults to OS HOME). Used by tests. */
|
|
25
|
+
userDir?: string;
|
|
26
|
+
/** Print intended actions without mutating the filesystem. */
|
|
27
|
+
dryRun?: boolean;
|
|
28
|
+
/** Overwrite a differing existing file (install only). */
|
|
29
|
+
force?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface AgentResult {
|
|
32
|
+
action: "installed" | "uninstalled" | "noop" | "dry-run" | "aborted";
|
|
33
|
+
/** Absolute path to the agent file that was (or would be) touched. */
|
|
34
|
+
targetPath: string;
|
|
35
|
+
/** Human-readable message for CLI output. */
|
|
36
|
+
message: string;
|
|
37
|
+
/** Non-empty when `action === "aborted"`. */
|
|
38
|
+
errorCode?: "differs-without-force" | "asset-missing" | "permission-denied" | "unknown";
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Absolute path to the shipped agent template. Resolves from the compiled
|
|
42
|
+
* `dist/cli/agent.js` (or `src/cli/agent.ts` under vitest) up to the package
|
|
43
|
+
* root — both layouts are `<pkg>/<dist|src>/cli/` so two `..` hops land at
|
|
44
|
+
* the root where `assets/agents/` lives.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getAgentAssetPath(): string;
|
|
47
|
+
export declare function getTargetAgentPath(userDir?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Minimal unified-style diff of two strings, used only to describe the
|
|
50
|
+
* discrepancy when the caller refuses `--force`. Intentionally naive: a line
|
|
51
|
+
* in `current` that is missing from `template` shows as `-`, and vice versa.
|
|
52
|
+
* Output is capped so a massive template drift cannot flood the terminal.
|
|
53
|
+
*/
|
|
54
|
+
export declare function summarizeDiff(current: string, template: string, maxLines?: number): string;
|
|
55
|
+
export declare function installAgent(opts?: AgentOptions): AgentResult;
|
|
56
|
+
export declare function uninstallAgent(opts?: AgentOptions): AgentResult;
|
|
57
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/cli/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAaH,eAAO,MAAM,sBAAsB,0BAA0B,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACrE,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,uBAAuB,GAAG,eAAe,GAAG,mBAAmB,GAAG,SAAS,CAAC;CACzF;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAgBtF;AAMD,wBAAgB,YAAY,CAAC,IAAI,GAAE,YAAiB,GAAG,WAAW,CAkEjE;AAED,wBAAgB,cAAc,CAAC,IAAI,GAAE,YAAiB,GAAG,WAAW,CAoCnE"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom agent installer for Distill (US-016).
|
|
3
|
+
*
|
|
4
|
+
* Extends `distill-mcp setup` with `--install-agent` and `--uninstall-agent`,
|
|
5
|
+
* copying the shipped `distill-compressor.md` template (US-015) from the
|
|
6
|
+
* package `assets/agents/` directory into `<userDir>/.claude/agents/`.
|
|
7
|
+
*
|
|
8
|
+
* Design invariants mirror the PreCompact hook installer:
|
|
9
|
+
* - Idempotent: installing when the target file already matches the template
|
|
10
|
+
* is a no-op; re-running produces no filesystem churn.
|
|
11
|
+
* - Atomic: overwrites go through `writeAtomic` (tempfile + rename) so a
|
|
12
|
+
* SIGTERM mid-install leaves either the pre-state or the post-state,
|
|
13
|
+
* never a half-written file.
|
|
14
|
+
* - Non-destructive by default: when the target exists and differs from the
|
|
15
|
+
* template, we abort with a line-level diff unless the caller passes
|
|
16
|
+
* `force: true`.
|
|
17
|
+
* - Dry-run surfaces intended actions without touching disk.
|
|
18
|
+
*
|
|
19
|
+
* Per project convention (CLAUDE.md: "Manual process.argv parsing in
|
|
20
|
+
* bin/cli.js"), this module pulls in no new runtime dependencies.
|
|
21
|
+
*/
|
|
22
|
+
import * as fs from "node:fs";
|
|
23
|
+
import * as os from "node:os";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
import { fileURLToLocalPath } from "./utils.js";
|
|
26
|
+
import { writeAtomic } from "./precompact.js";
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Constants & types
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
export const DISTILL_AGENT_FILENAME = "distill-compressor.md";
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Path resolution
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Absolute path to the shipped agent template. Resolves from the compiled
|
|
36
|
+
* `dist/cli/agent.js` (or `src/cli/agent.ts` under vitest) up to the package
|
|
37
|
+
* root — both layouts are `<pkg>/<dist|src>/cli/` so two `..` hops land at
|
|
38
|
+
* the root where `assets/agents/` lives.
|
|
39
|
+
*/
|
|
40
|
+
export function getAgentAssetPath() {
|
|
41
|
+
const here = path.dirname(fileURLToLocalPath(import.meta.url));
|
|
42
|
+
return path.resolve(here, "..", "..", "assets", "agents", DISTILL_AGENT_FILENAME);
|
|
43
|
+
}
|
|
44
|
+
export function getTargetAgentPath(userDir) {
|
|
45
|
+
const root = userDir ?? os.homedir();
|
|
46
|
+
return path.join(root, ".claude", "agents", DISTILL_AGENT_FILENAME);
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Diff helper (line-level, zero deps)
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Minimal unified-style diff of two strings, used only to describe the
|
|
53
|
+
* discrepancy when the caller refuses `--force`. Intentionally naive: a line
|
|
54
|
+
* in `current` that is missing from `template` shows as `-`, and vice versa.
|
|
55
|
+
* Output is capped so a massive template drift cannot flood the terminal.
|
|
56
|
+
*/
|
|
57
|
+
export function summarizeDiff(current, template, maxLines = 40) {
|
|
58
|
+
const a = current.split("\n");
|
|
59
|
+
const b = template.split("\n");
|
|
60
|
+
const setA = new Set(a);
|
|
61
|
+
const setB = new Set(b);
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const l of a) {
|
|
64
|
+
if (!setB.has(l))
|
|
65
|
+
lines.push(`- ${l}`);
|
|
66
|
+
}
|
|
67
|
+
for (const l of b) {
|
|
68
|
+
if (!setA.has(l))
|
|
69
|
+
lines.push(`+ ${l}`);
|
|
70
|
+
}
|
|
71
|
+
if (lines.length === 0)
|
|
72
|
+
return "(no line-level differences — only ordering or whitespace changes)";
|
|
73
|
+
if (lines.length <= maxLines)
|
|
74
|
+
return lines.join("\n");
|
|
75
|
+
const head = lines.slice(0, maxLines);
|
|
76
|
+
return head.join("\n") + `\n… (${lines.length - maxLines} more diff lines omitted)`;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Public install / uninstall
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export function installAgent(opts = {}) {
|
|
82
|
+
const targetPath = getTargetAgentPath(opts.userDir);
|
|
83
|
+
const assetPath = getAgentAssetPath();
|
|
84
|
+
if (!fs.existsSync(assetPath)) {
|
|
85
|
+
return {
|
|
86
|
+
action: "aborted",
|
|
87
|
+
targetPath,
|
|
88
|
+
message: `Aborted: agent template not found at ${assetPath}. The distill-mcp package may be corrupted — reinstall it.`,
|
|
89
|
+
errorCode: "asset-missing",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const templateContent = fs.readFileSync(assetPath, "utf-8");
|
|
93
|
+
const targetExists = fs.existsSync(targetPath);
|
|
94
|
+
if (targetExists) {
|
|
95
|
+
const existingContent = fs.readFileSync(targetPath, "utf-8");
|
|
96
|
+
if (existingContent === templateContent) {
|
|
97
|
+
return {
|
|
98
|
+
action: "noop",
|
|
99
|
+
targetPath,
|
|
100
|
+
message: `Agent already installed at ${targetPath} (content matches; no change).`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (!opts.force) {
|
|
104
|
+
const diff = summarizeDiff(existingContent, templateContent);
|
|
105
|
+
return {
|
|
106
|
+
action: "aborted",
|
|
107
|
+
targetPath,
|
|
108
|
+
message: `Aborted: ${targetPath} exists and differs from the shipped template.\n` +
|
|
109
|
+
`Pass --force to overwrite, or --uninstall-agent first.\n` +
|
|
110
|
+
`Diff (existing → template):\n${diff}`,
|
|
111
|
+
errorCode: "differs-without-force",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (opts.dryRun) {
|
|
116
|
+
const verb = targetExists ? "overwrite (differs, --force set)" : "create";
|
|
117
|
+
return {
|
|
118
|
+
action: "dry-run",
|
|
119
|
+
targetPath,
|
|
120
|
+
message: `[dry-run] Would ${verb} ${targetPath} (${templateContent.length} bytes from ${assetPath}).`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
writeAtomic(targetPath, templateContent, 0o644);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
128
|
+
return {
|
|
129
|
+
action: "aborted",
|
|
130
|
+
targetPath,
|
|
131
|
+
message: `Failed to write ${targetPath}: ${message}`,
|
|
132
|
+
errorCode: isPermissionError(err) ? "permission-denied" : "unknown",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const verb = targetExists ? "Overwrote" : "Installed";
|
|
136
|
+
return {
|
|
137
|
+
action: "installed",
|
|
138
|
+
targetPath,
|
|
139
|
+
message: `${verb} distill-compressor agent → ${targetPath}.`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function uninstallAgent(opts = {}) {
|
|
143
|
+
const targetPath = getTargetAgentPath(opts.userDir);
|
|
144
|
+
if (!fs.existsSync(targetPath)) {
|
|
145
|
+
return {
|
|
146
|
+
action: "noop",
|
|
147
|
+
targetPath,
|
|
148
|
+
message: `No distill-compressor agent at ${targetPath} — nothing to uninstall.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (opts.dryRun) {
|
|
152
|
+
return {
|
|
153
|
+
action: "dry-run",
|
|
154
|
+
targetPath,
|
|
155
|
+
message: `[dry-run] Would delete ${targetPath}.`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
fs.unlinkSync(targetPath);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
+
return {
|
|
164
|
+
action: "aborted",
|
|
165
|
+
targetPath,
|
|
166
|
+
message: `Failed to delete ${targetPath}: ${message}`,
|
|
167
|
+
errorCode: isPermissionError(err) ? "permission-denied" : "unknown",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
action: "uninstalled",
|
|
172
|
+
targetPath,
|
|
173
|
+
message: `Uninstalled distill-compressor agent from ${targetPath}.`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function isPermissionError(err) {
|
|
177
|
+
if (!err || typeof err !== "object")
|
|
178
|
+
return false;
|
|
179
|
+
const code = err.code;
|
|
180
|
+
return code === "EACCES" || code === "EPERM";
|
|
181
|
+
}
|
package/dist/cli/hooks.d.ts
CHANGED
|
@@ -11,4 +11,13 @@ export interface InstallHooksOptions {
|
|
|
11
11
|
force?: boolean;
|
|
12
12
|
}
|
|
13
13
|
export declare function installHooks(options?: InstallHooksOptions): Promise<boolean>;
|
|
14
|
+
export interface UpdateClaudeMdOptions {
|
|
15
|
+
projectDir?: string;
|
|
16
|
+
force?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Updates CLAUDE.md with Distill MCP directives.
|
|
20
|
+
* Returns true if updated, false if CLAUDE.md doesn't exist.
|
|
21
|
+
*/
|
|
22
|
+
export declare function updateClaudeMd(options?: UpdateClaudeMdOptions): boolean;
|
|
14
23
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/cli/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/cli/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/cli/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgRH,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAqGtF;AAgBD,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CA0D3E"}
|
package/dist/cli/hooks.js
CHANGED
|
@@ -6,10 +6,120 @@
|
|
|
6
6
|
* - PostToolUse: Reminds to use auto_optimize for large Bash outputs
|
|
7
7
|
* - UserPromptSubmit: Injects MCP tool reminders
|
|
8
8
|
*/
|
|
9
|
-
import { existsSync, mkdirSync, writeFileSync, chmodSync } from "fs";
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync, chmodSync, readFileSync } from "fs";
|
|
10
10
|
import { join } from "path";
|
|
11
11
|
import { success, warn, info, error, log, COLORS, readJSONFile, writeJSONFile } from "./utils.js";
|
|
12
12
|
// ============================================================================
|
|
13
|
+
// CLAUDE.md Content
|
|
14
|
+
// ============================================================================
|
|
15
|
+
const CLAUDE_MD_SECTION_START = "## Directives d'utilisation des outils MCP";
|
|
16
|
+
const CLAUDE_MD_SECTION_END = "<!-- END DISTILL -->";
|
|
17
|
+
const CLAUDE_MD_CONTENT = `## Directives d'utilisation des outils MCP
|
|
18
|
+
|
|
19
|
+
Utilisez les outils Distill MCP pour des opérations économes en tokens :
|
|
20
|
+
|
|
21
|
+
### Règle 1 : Lecture intelligente de fichiers
|
|
22
|
+
|
|
23
|
+
Lors de la lecture de fichiers source pour **exploration ou compréhension** :
|
|
24
|
+
|
|
25
|
+
\`\`\`
|
|
26
|
+
mcp__distill__smart_file_read filePath="path/to/file.ts"
|
|
27
|
+
\`\`\`
|
|
28
|
+
|
|
29
|
+
**Quand utiliser Read natif à la place :**
|
|
30
|
+
- Avant d'éditer un fichier (Edit nécessite Read d'abord)
|
|
31
|
+
- Fichiers de configuration : \`.json\`, \`.yaml\`, \`.toml\`, \`.md\`, \`.env\`
|
|
32
|
+
|
|
33
|
+
### Règle 2 : Compresser les sorties volumineuses
|
|
34
|
+
|
|
35
|
+
Après les commandes Bash qui produisent une sortie volumineuse (>500 caractères) :
|
|
36
|
+
|
|
37
|
+
\`\`\`
|
|
38
|
+
mcp__distill__auto_optimize content="<collez la sortie volumineuse>"
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
### Règle 3 : SDK d'exécution de code pour les opérations complexes
|
|
42
|
+
|
|
43
|
+
Pour les opérations multi-étapes, utilisez \`code_execute\` au lieu de plusieurs appels d'outils (**98% d'économie de tokens**) :
|
|
44
|
+
|
|
45
|
+
\`\`\`
|
|
46
|
+
mcp__distill__code_execute code="<code typescript>"
|
|
47
|
+
\`\`\`
|
|
48
|
+
|
|
49
|
+
**API du SDK (\`ctx\`) :**
|
|
50
|
+
|
|
51
|
+
*Compression :*
|
|
52
|
+
- \`ctx.compress.auto(content, hint?)\` - Détection auto et compression
|
|
53
|
+
- \`ctx.compress.logs(logs)\` - Résumer les logs
|
|
54
|
+
- \`ctx.compress.diff(diff)\` - Compresser les git diff
|
|
55
|
+
- \`ctx.compress.semantic(content, ratio?)\` - Compression TF-IDF
|
|
56
|
+
|
|
57
|
+
*Code :*
|
|
58
|
+
- \`ctx.code.parse(content, lang)\` - Parser en structure AST
|
|
59
|
+
- \`ctx.code.extract(content, lang, {type, name})\` - Extraire un élément
|
|
60
|
+
- \`ctx.code.skeleton(content, lang)\` - Obtenir les signatures uniquement
|
|
61
|
+
|
|
62
|
+
*Fichiers :*
|
|
63
|
+
- \`ctx.files.read(path)\` - Lire le contenu d'un fichier
|
|
64
|
+
- \`ctx.files.exists(path)\` - Vérifier si un fichier existe
|
|
65
|
+
- \`ctx.files.glob(pattern)\` - Trouver des fichiers par pattern
|
|
66
|
+
|
|
67
|
+
*Git :*
|
|
68
|
+
- \`ctx.git.diff(ref?)\` - Obtenir le diff git
|
|
69
|
+
- \`ctx.git.log(limit?)\` - Historique des commits
|
|
70
|
+
- \`ctx.git.status()\` - Statut du repo
|
|
71
|
+
- \`ctx.git.branch()\` - Info sur les branches
|
|
72
|
+
- \`ctx.git.blame(file, line?)\` - Git blame d'un fichier
|
|
73
|
+
|
|
74
|
+
*Recherche :*
|
|
75
|
+
- \`ctx.search.grep(pattern, glob?)\` - Rechercher un pattern dans les fichiers
|
|
76
|
+
- \`ctx.search.symbols(query, glob?)\` - Rechercher des symboles (fonctions, classes)
|
|
77
|
+
- \`ctx.search.files(pattern)\` - Rechercher des fichiers par pattern
|
|
78
|
+
- \`ctx.search.references(symbol, glob?)\` - Trouver les références d'un symbole
|
|
79
|
+
|
|
80
|
+
*Analyse :*
|
|
81
|
+
- \`ctx.analyze.dependencies(file)\` - Analyser les imports/exports
|
|
82
|
+
- \`ctx.analyze.callGraph(fn, file, depth?)\` - Construire le graphe d'appels
|
|
83
|
+
- \`ctx.analyze.exports(file)\` - Obtenir les exports d'un fichier
|
|
84
|
+
- \`ctx.analyze.structure(dir?, depth?)\` - Structure du répertoire avec analyse
|
|
85
|
+
|
|
86
|
+
*Utilitaires :*
|
|
87
|
+
- \`ctx.utils.countTokens(text)\` - Compter les tokens
|
|
88
|
+
- \`ctx.utils.detectType(content)\` - Détecter le type de contenu
|
|
89
|
+
- \`ctx.utils.detectLanguage(path)\` - Détecter le langage depuis le chemin
|
|
90
|
+
|
|
91
|
+
**Exemples :**
|
|
92
|
+
|
|
93
|
+
\`\`\`typescript
|
|
94
|
+
// Obtenir les squelettes de tous les fichiers TypeScript
|
|
95
|
+
const files = ctx.files.glob("src/**/*.ts").slice(0, 5);
|
|
96
|
+
return files.map(f => ({
|
|
97
|
+
file: f,
|
|
98
|
+
skeleton: ctx.code.skeleton(ctx.files.read(f), "typescript")
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
// Compresser et analyser les logs
|
|
102
|
+
const logs = ctx.files.read("server.log");
|
|
103
|
+
return ctx.compress.logs(logs);
|
|
104
|
+
|
|
105
|
+
// Extraire une fonction spécifique
|
|
106
|
+
const content = ctx.files.read("src/api.ts");
|
|
107
|
+
return ctx.code.extract(content, "typescript", { type: "function", name: "handleRequest" });
|
|
108
|
+
\`\`\`
|
|
109
|
+
|
|
110
|
+
### Référence rapide
|
|
111
|
+
|
|
112
|
+
| Action | Utiliser |
|
|
113
|
+
|--------|----------|
|
|
114
|
+
| Lire du code pour exploration | \`mcp__distill__smart_file_read filePath="file.ts"\` |
|
|
115
|
+
| Obtenir une fonction/classe | \`mcp__distill__smart_file_read filePath="file.ts" target={"type":"function","name":"myFunc"}\` |
|
|
116
|
+
| Compresser les erreurs de build | \`mcp__distill__auto_optimize content="..."\` |
|
|
117
|
+
| Résumer les logs | \`mcp__distill__auto_optimize content="..." strategy="logs"\` |
|
|
118
|
+
| Opérations multi-étapes | \`mcp__distill__code_execute code="return ctx.files.glob('src/**/*.ts')"\` |
|
|
119
|
+
| Avant d'éditer | Utiliser l'outil natif \`Read\` |
|
|
120
|
+
|
|
121
|
+
<!-- END DISTILL -->`;
|
|
122
|
+
// ============================================================================
|
|
13
123
|
// Hook Script Templates
|
|
14
124
|
// ============================================================================
|
|
15
125
|
const PRE_READ_CHECK_SCRIPT = `#!/bin/bash
|
|
@@ -66,7 +176,7 @@ if echo "$TOOL_RESPONSE" | grep -qiE "(error TS|warning TS|error\\[E|npm ERR|ERR
|
|
|
66
176
|
fi
|
|
67
177
|
|
|
68
178
|
if echo "$TOOL_RESPONSE" | grep -qiE "(\\[INFO\\]|\\[ERROR\\]|\\[WARN\\]|\\[DEBUG\\]|[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2})"; then
|
|
69
|
-
echo '{"systemMessage": "TIP: Large log output detected. Use
|
|
179
|
+
echo '{"systemMessage": "TIP: Large log output detected. Use mcp__distill__auto_optimize with strategy=logs to compress (80-90% reduction)."}'
|
|
70
180
|
exit 0
|
|
71
181
|
fi
|
|
72
182
|
|
|
@@ -82,8 +192,8 @@ cat << 'EOF'
|
|
|
82
192
|
<user-prompt-submit-hook>
|
|
83
193
|
DISTILL REMINDER: Use MCP tools for token optimization:
|
|
84
194
|
- Code files: mcp__distill__smart_file_read (50-70% savings vs Read)
|
|
85
|
-
- Build/test output: mcp__distill__auto_optimize
|
|
86
|
-
-
|
|
195
|
+
- Build/test output: mcp__distill__auto_optimize (95%+ reduction)
|
|
196
|
+
- Multi-step ops: mcp__distill__code_execute (98% savings via SDK)
|
|
87
197
|
</user-prompt-submit-hook>
|
|
88
198
|
EOF
|
|
89
199
|
exit 0
|
|
@@ -209,7 +319,7 @@ export async function installHooks(options = {}) {
|
|
|
209
319
|
log(`\n${COLORS.dim}Token savings:${COLORS.reset}`);
|
|
210
320
|
log(` • smart_file_read: 50-70% reduction vs Read`);
|
|
211
321
|
log(` • auto_optimize: 95%+ reduction on build errors`);
|
|
212
|
-
log(` •
|
|
322
|
+
log(` • auto_optimize: 80-90% reduction on logs\n`);
|
|
213
323
|
return true;
|
|
214
324
|
}
|
|
215
325
|
else {
|
|
@@ -227,3 +337,64 @@ function checkJqInstalled() {
|
|
|
227
337
|
return false;
|
|
228
338
|
}
|
|
229
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Updates CLAUDE.md with Distill MCP directives.
|
|
342
|
+
* Returns true if updated, false if CLAUDE.md doesn't exist.
|
|
343
|
+
*/
|
|
344
|
+
export function updateClaudeMd(options = {}) {
|
|
345
|
+
const projectDir = options.projectDir || process.cwd();
|
|
346
|
+
const force = options.force || false;
|
|
347
|
+
const claudeMdPath = join(projectDir, "CLAUDE.md");
|
|
348
|
+
// Check if CLAUDE.md exists
|
|
349
|
+
if (!existsSync(claudeMdPath)) {
|
|
350
|
+
warn("CLAUDE.md not found.");
|
|
351
|
+
log(`\n${COLORS.dim}To create CLAUDE.md, run in Claude Code:${COLORS.reset}`);
|
|
352
|
+
log(` ${COLORS.cyan}/init${COLORS.reset}`);
|
|
353
|
+
log(`\nThen run setup again to add Distill directives.\n`);
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
// Read existing content
|
|
357
|
+
let content;
|
|
358
|
+
try {
|
|
359
|
+
content = readFileSync(claudeMdPath, "utf-8");
|
|
360
|
+
}
|
|
361
|
+
catch (err) {
|
|
362
|
+
error(`Failed to read CLAUDE.md: ${err}`);
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
// Check if Distill section already exists
|
|
366
|
+
const sectionStartIndex = content.indexOf(CLAUDE_MD_SECTION_START);
|
|
367
|
+
const sectionEndIndex = content.indexOf(CLAUDE_MD_SECTION_END);
|
|
368
|
+
let newContent;
|
|
369
|
+
if (sectionStartIndex !== -1 && sectionEndIndex !== -1) {
|
|
370
|
+
// Section exists - replace it
|
|
371
|
+
if (!force) {
|
|
372
|
+
info("Distill directives already present in CLAUDE.md. Use --force to update.");
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
// Replace existing section
|
|
376
|
+
const beforeSection = content.substring(0, sectionStartIndex).trimEnd();
|
|
377
|
+
const afterSection = content.substring(sectionEndIndex + CLAUDE_MD_SECTION_END.length).trimStart();
|
|
378
|
+
newContent = beforeSection + "\n\n" + CLAUDE_MD_CONTENT + (afterSection ? "\n\n" + afterSection : "\n");
|
|
379
|
+
}
|
|
380
|
+
else if (sectionStartIndex !== -1) {
|
|
381
|
+
// Partial section (start found but no end marker) - warn and skip
|
|
382
|
+
warn("Found partial Distill section in CLAUDE.md without end marker.");
|
|
383
|
+
log(`Add ${COLORS.dim}${CLAUDE_MD_SECTION_END}${COLORS.reset} at the end of the section, then run setup again.`);
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
// No section exists - append
|
|
388
|
+
newContent = content.trimEnd() + "\n\n" + CLAUDE_MD_CONTENT + "\n";
|
|
389
|
+
}
|
|
390
|
+
// Write updated content
|
|
391
|
+
try {
|
|
392
|
+
writeFileSync(claudeMdPath, newContent, "utf-8");
|
|
393
|
+
success("Updated CLAUDE.md with Distill directives");
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
catch (err) {
|
|
397
|
+
error(`Failed to write CLAUDE.md: ${err}`);
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { setup, parseSetupArgs, type SetupOptions } from "./setup.js";
|
|
2
2
|
export { doctor } from "./doctor.js";
|
|
3
|
-
export { installHooks, type InstallHooksOptions } from "./hooks.js";
|
|
3
|
+
export { installHooks, updateClaudeMd, type InstallHooksOptions, type UpdateClaudeMdOptions } from "./hooks.js";
|
|
4
4
|
export * from "./utils.js";
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAChH,cAAc,YAAY,CAAC"}
|
package/dist/cli/index.js
CHANGED