Dynamic Context Pruning extension for pi - intelligently removes obsolete messages to optimize token usage
Intelligently prunes conversation context to optimize token usage while preserving conversation coherence.
- Deduplication: Removes duplicate tool outputs based on content hash
- Superseded Writes: Removes older file writes when newer versions exist
- Error Purging: Removes resolved errors from context
- Recency Protection: Always preserves recent messages
Clone the repository into your pi agent extensions directory:
``bash`
git clone https://github.com/zenobi-us/pi-dcp.git ~/.pi/agent/extensions/pi-dcp
The extension runs automatically on every LLM call. No manual intervention needed.
- /dcp-debug - Toggle debug logging/dcp-stats
- - Show pruning statistics for current session/dcp-toggle
- - Enable/disable the extension/dcp-recent
- - Set how many recent messages to always keep (default: 10)
- --dcp-enabled=true/false - Enable/disable extension at startup--dcp-debug=true/false
- - Enable debug logging at startup
1. Prepare Phase: Rules annotate message metadata
2. Process Phase: Rules make pruning decisions based on metadata
3. Filter Phase: Messages marked for pruning are removed
Located in src/rules/:
1. Deduplication (deduplication.ts)
- Prepare: Hash message content
- Process: Mark duplicates for pruning
2. Superseded Writes (superseded-writes.ts)
- Prepare: Extract file paths from write/edit operations
- Process: Mark older writes to the same file for pruning
3. Error Purging (error-purging.ts)
- Prepare: Identify errors and check if resolved
- Process: Mark resolved errors for pruning
4. Recency (recency.ts)
- Process: Protect last N messages from pruning (overrides other rules)
Default configuration in src/config.ts:
`typescript`
{
enabled: true,
debug: false,
rules: ['deduplication', 'superseded-writes', 'error-purging', 'recency'],
keepRecentCount: 10
}
Create custom pruning rules by implementing the PruneRule interface:
`typescript
import type { PruneRule } from "./src/types";
const myRule: PruneRule = {
name: 'my-custom-rule',
description: 'My custom pruning logic',
prepare(msg, ctx) {
// Annotate metadata during prepare phase
msg.metadata.myScore = calculateScore(msg.message);
},
process(msg, ctx) {
// Make pruning decision during process phase
if (msg.metadata.myScore < threshold) {
msg.metadata.shouldPrune = true;
msg.metadata.pruneReason = 'low score';
}
},
};
`
Then add to configuration: rules: ['deduplication', myRule]
`bash`
bun run typecheck
``
pi-dcp/
├── index.ts # Main extension entry point
├── package.json # Bun package config
├── tsconfig.json # TypeScript config
├── src/
│ ├── types.ts # Core type definitions
│ ├── config.ts # Configuration management
│ ├── metadata.ts # Message metadata utilities
│ ├── registry.ts # Rule registration system
│ ├── workflow.ts # Prepare > Process > Filter workflow
│ └── rules/
│ ├── index.ts # Export and register all rules
│ ├── deduplication.ts
│ ├── superseded-writes.ts
│ ├── error-purging.ts
│ └── recency.ts
└── README.md
1. Context Event Hook: The extension subscribes to the context event, which fires before each LLM callprepare
2. Message Processing: All messages are wrapped with metadata containers
3. Prepare Phase: Each rule's function annotates metadata (hashes, file paths, etc.)process
4. Process Phase: Each rule's function makes pruning decisions based on metadatashouldPrune: true
5. Filter Phase: Messages marked with are removed
6. Result: Pruned message list is returned to pi and sent to the LLM
- Token Savings: Removes redundant and obsolete messages
- Cost Reduction: Fewer tokens = lower API costs
- Preserved Coherence: Smart rules keep important context
- Transparent: No changes to user experience
- Configurable: Adjust rules and thresholds as needed
- Extensible: Easy to add custom rules
``
[pi-dcp] Initialized with 4 rules: deduplication, superseded-writes, error-purging, recency
[pi-dcp] Pruned 12 / 45 messages
[pi-dcp] Pruned 8 / 52 messages
With debug mode enabled (/dcp-debug):
```
[pi-dcp] Dedup: marking duplicate message at index 15 (hash: k2l9x)
[pi-dcp] SupersededWrites: found file operation at index 23: src/index.ts
[pi-dcp] SupersededWrites: marking superseded write at index 23: src/index.ts
[pi-dcp] ErrorPurging: found resolved error at index 31
[pi-dcp] Recency: protecting message at index 48 (distance from end: 3, threshold: 10)
[pi-dcp] Filter phase complete: 12 pruned, 33 kept (45 total)
[pi-dcp] Pruned messages:
[15] assistant: duplicate content
[23] toolResult: superseded by later write to src/index.ts
[31] toolResult: error resolved by later success
...
MIT