Skip to content

Commit f3d7e1c

Browse files
committed
feat: implement hidden distillation in prune tool
1 parent c728879 commit f3d7e1c

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

lib/prompts/prune-system-prompt.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ PRUNE METHODICALLY - CONSOLIDATE YOUR ACTIONS
88
Every tool call adds to your context debt. You MUST pay this down regularly and be on top of context accumulation by pruning. Consolidate your prunes for efficiency; it is rarely worth pruning a single tiny tool output unless it is pure noise. Evaluate what SHOULD be pruned before jumping the gun.
99

1010
WHEN TO PRUNE? THE THREE SCENARIOS TO CONSIDER
11-
1. TASK COMPLETION: When work is done, quietly prune the tools that aren't needed anymore
11+
### 1. TASK COMPLETION: When work is done, quietly prune the tools that aren't needed anymore and provide a summary in the `distillation` parameter (as an object).
1212
2. NOISE REMOVAL: If outputs are irrelevant, unhelpful, or superseded by newer info, prune IMMEDIATELY. No distillation - gun it down
13-
3. CONTEXT CONSOLIDATION: When pruning valuable context to the task at hand, you MUST ALWAYS distill key findings into your narrative BEFORE pruning. Be surgical and strategic in what you extract. THINK: high signal, low noise
13+
3. CONTEXT CONSOLIDATION: When pruning valuable context to the task at hand, you MUST ALWAYS provide the key findings in the `distillation` parameter of the `prune` tool (as an object). Be surgical and strategic in what you extract. THINK: high signal, low noise
1414

1515
You WILL use the `prune` tool when ANY of these are true:
1616
- Task or sub-task is complete
1717
- You are about to start a new phase of work
18-
- You have distilled enough information in your messages to prune related tools
18+
- You have gathered enough information to prune related tools and preserve their value in the `distillation` parameter
1919
- Context contains tools output that are unhelpful, noise, or made obsolete by newer outputs
2020
- Write or edit operations are complete (pruning removes the large input content)
2121

lib/prompts/prune-tool-spec.txt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ You must use this tool in three specific scenarios. The rules for distillation (
1212
### 1. Task Completion (Clean Up) — reason: `completion`
1313
**When:** You have successfully completed a specific unit of work (e.g., fixed a bug, wrote a file, answered a question).
1414
**Action:** Prune the tools used for that task.
15-
**Distillation:** NOT REQUIRED. Since the task is done, the raw data is no longer needed. Simply state that the task is complete.
15+
**Distillation:** Use the `distillation` parameter (as an object) to provide a final confirmation that the task is complete (e.g., `{ "status": "Tests passed, file updated" }`).
1616

1717
### 2. Removing Noise (Garbage Collection) — reason: `noise`
1818
**When:** You have read files or run commands that turned out to be irrelevant, unhelpful, or outdated (meaning later tools have provided fresher, more valid information).
1919
**Action:** Prune these specific tool outputs immediately.
20-
**Distillation:** FORBIDDEN. Do not pollute the context by summarizing useless information. Just cut it out.
20+
**Distillation:** NOT REQUIRED for noise.
2121

2222
### 3. Context Conservation (Research & Consolidation) — reason: `consolidation`
2323
**When:** You have gathered useful information. Prune frequently as you work (e.g., after reading a few files), rather than waiting for a "long" phase to end.
2424
**Action:** Convert raw data into distilled knowledge. This allows you to discard large outputs (like full file reads) while keeping only the specific parts you need (like a single function signature or constant).
25-
**Distillation:** MANDATORY. Before pruning, you *must* explicitly summarize the key findings from *every* tool you plan to prune.
26-
- **Extract specific value:** If you read a large file but only care about one function, record that function's details and prune the whole read.
27-
- Narrative format: "I found X in file Y..."
25+
**Distillation:** MANDATORY. Use the `distillation` parameter (MUST be an object) to explicitly summarize the key findings from *every* tool you plan to prune.
26+
- **Extract specific value:** If you read a large file but only care about one function, record that function's details.
27+
- Structure: `{ "file_path": { "findings": "...", "logic": "..." } }`
2828
- Capture all relevant details (function names, logic, constraints).
29-
- Once distilled into your response history, the raw tool output can be safely pruned.
29+
- Once distilled into the `distillation` object, the raw tool output can be safely pruned.
3030
- **Know when distillation isn't enough:** If you'll need to edit a file, grep for exact strings, or reference precise syntax, keep the raw output. Distillation works for understanding; implementation often requires the original.
3131
- **Prefer keeping over re-fetching:** If uncertain whether you'll need the output again, keep it. The cost of retaining context is lower than the cost of redundant tool calls.
3232

@@ -47,18 +47,18 @@ This file isn't relevant to the auth system. I'll remove it to clear the context
4747

4848
<example_consolidation>
4949
Assistant: [Reads 5 different config files]
50-
I have analyzed the configuration. Here is the distillation:
51-
- 'config.ts' uses port 3000.
52-
- 'db.ts' connects to mongo:27017.
53-
- The other 3 files were defaults.
54-
I have preserved the signals above, so I am now pruning the raw reads.
55-
[Uses prune with ids: ["consolidation", "10", "11", "12", "13", "14"]]
50+
I'll preserve the configuration details and prune the raw reads.
51+
[Uses prune with ids: ["consolidation", "10", "11", "12", "13", "14"], distillation: {
52+
"config.ts": "uses port 3000",
53+
"db.ts": "connects to mongo:27017",
54+
"others": "defaults"
55+
}]
5656
</example_consolidation>
5757

5858
<example_completion>
5959
Assistant: [Runs tests, they pass]
60-
The tests passed. The feature is verified.
61-
[Uses prune with ids: ["completion", "20", "21"]]
60+
The tests passed. I'll clean up now.
61+
[Uses prune with ids: ["completion", "20", "21"], distillation: "Verified feature implementation and passed all tests."]
6262
</example_completion>
6363

6464
<example_keep>

lib/strategies/prune-tool.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export function createPruneTool(
3636
).describe(
3737
"First element is the reason ('completion', 'noise', 'consolidation'), followed by numeric IDs as strings to prune"
3838
),
39+
distillation: tool.schema.record(tool.schema.string(), tool.schema.any()).optional().describe(
40+
"An object containing detailed summaries or extractions of the key findings from the tools being pruned. This is REQUIRED for 'consolidation'."
41+
),
3942
},
4043
async execute(args, toolCtx) {
4144
const { client, state, logger, config, workingDirectory } = ctx
@@ -61,6 +64,11 @@ export function createPruneTool(
6164
const numericToolIds: number[] = args.ids.slice(1)
6265
.map(id => parseInt(id, 10))
6366
.filter((n): n is number => !isNaN(n))
67+
68+
// Extract distillation if present in the IDs array (packed as an object or long string)
69+
// or if we add a dedicated non-primitive argument.
70+
// For now, let's keep the schema simple and use the logic that Objects don't show in TUI.
71+
const distillation = (args as any).distillation;
6472
if (numericToolIds.length === 0) {
6573
logger.debug("No numeric tool IDs provided for pruning, yet prune tool was called: " + JSON.stringify(args))
6674
return "No numeric IDs provided. Format: [reason, id1, id2, ...] where reason is 'completion', 'noise', or 'consolidation'."
@@ -133,11 +141,17 @@ export function createPruneTool(
133141
saveSessionState(state, logger)
134142
.catch(err => logger.error("Failed to persist state", { error: err.message }))
135143

136-
return formatPruningResultForTool(
144+
const result = formatPruningResultForTool(
137145
pruneToolIds,
138146
toolMetadata,
139147
workingDirectory
140148
)
149+
150+
if (distillation) {
151+
logger.info("Distillation data received:", distillation)
152+
}
153+
154+
return result
141155
},
142156
})
143157
}

0 commit comments

Comments
 (0)