mirror of
https://github.com/wassname/pi-dynamic-context-pruning.git
synced 2026-06-27 18:05:36 +08:00
147 lines
5.6 KiB
Markdown
147 lines
5.6 KiB
Markdown
# Dynamic Context Pruning (DCP) for Pi
|
|
|
|
Automatically reduces token usage in Pi coding agent sessions by managing conversation context through compression, deduplication, and smart nudges.
|
|
|
|
## Features
|
|
|
|
- **Compress tool** — LLM-callable tool that replaces stale conversation ranges with exhaustive technical summaries, preserving full context fidelity at a fraction of the token cost
|
|
- **Deduplication** — automatically removes duplicate tool call outputs (same tool, same args) keeping only the most recent result
|
|
- **Error purging** — cleans up failed tool inputs after a configurable number of user turns
|
|
- **Context nudges** — injects compression reminders into the context at configurable thresholds: soft housekeeping notices, strong emergency warnings, and iteration reminders after long tool-call chains
|
|
- **Manual mode** — disable autonomous compression nudges; trigger compression only via `/dcp compress` or explicit user request
|
|
- **Session persistence** — compression blocks and pruning state survive session restarts
|
|
- **`/dcp` commands** — inspect context usage, view stats, sweep tool outputs, and manage compression blocks interactively
|
|
|
|
## Installation
|
|
|
|
### Global (applies to all pi sessions)
|
|
|
|
```bash
|
|
pi install npm:@complexthings/pi-dynamic-context-pruning
|
|
```
|
|
|
|
### Install globally from GitHub
|
|
|
|
```bash
|
|
pi install https://github.com/complexthings/pi-dynamic-context-pruning
|
|
```
|
|
|
|
### Try it without installing
|
|
|
|
```bash
|
|
pi -e https://github.com/complexthings/pi-dynamic-context-pruning
|
|
```
|
|
|
|
## Configuration
|
|
|
|
DCP uses a layered configuration system (later layers override earlier ones):
|
|
|
|
1. Built-in defaults
|
|
2. `~/.config/pi/dcp.jsonc` — global user config (auto-created with defaults on first run)
|
|
3. `$PI_CONFIG_DIR/dcp.jsonc` — if the env var is set
|
|
4. `<project>/.pi/dcp.jsonc` — project-local overrides (walk up from cwd)
|
|
|
|
### Example: `~/.config/pi/dcp.jsonc`
|
|
|
|
```jsonc
|
|
{
|
|
// Disable the extension entirely
|
|
// "enabled": false,
|
|
|
|
// Start every session in manual mode
|
|
// "manualMode": { "enabled": true, "automaticStrategies": true },
|
|
|
|
"compress": {
|
|
// Above 80 % context: fire a nudge (every nudgeFrequency context events)
|
|
"maxContextPercent": 0.8,
|
|
// Below 40 % context: no nudges
|
|
"minContextPercent": 0.4,
|
|
// How many context events between nudges
|
|
"nudgeFrequency": 5,
|
|
// Nudge after this many tool calls since the last user message
|
|
"iterationNudgeThreshold": 15,
|
|
// "strong" = emergency tone, "soft" = housekeeping tone
|
|
"nudgeForce": "soft",
|
|
// These tool outputs are never auto-pruned
|
|
"protectedTools": ["compress", "write", "edit"]
|
|
},
|
|
"strategies": {
|
|
"deduplication": {
|
|
"enabled": true,
|
|
// Additional tools to exclude from dedup
|
|
"protectedTools": []
|
|
},
|
|
"purgeErrors": {
|
|
"enabled": true,
|
|
// Purge failed tool inputs after N user turns
|
|
"turns": 4,
|
|
"protectedTools": []
|
|
}
|
|
},
|
|
// Glob patterns — matching file paths are never pruned
|
|
"protectedFilePatterns": [],
|
|
// "off" | "minimal" | "detailed"
|
|
"pruneNotification": "detailed"
|
|
}
|
|
```
|
|
|
|
## Commands
|
|
|
|
All commands are available in the pi TUI via `/dcp <subcommand>`:
|
|
|
|
| Command | Description |
|
|
|---|---|
|
|
| `/dcp` or `/dcp help` | Show command reference |
|
|
| `/dcp context` | Show context window usage and session stats |
|
|
| `/dcp stats` | Show pruning statistics (tokens saved, blocks, operations) |
|
|
| `/dcp sweep [N]` | Mark last N tool outputs for pruning (default: all since last user message) |
|
|
| `/dcp manual` | Show current manual mode status |
|
|
| `/dcp manual on` | Enable manual mode — autonomous nudges disabled |
|
|
| `/dcp manual off` | Disable manual mode — autonomous nudges re-enabled |
|
|
| `/dcp compress` | Trigger LLM compression immediately (sends a followUp message) |
|
|
| `/dcp decompress` | List all active compression blocks |
|
|
| `/dcp decompress N` | Restore compression block `bN` (re-expands it in context) |
|
|
|
|
## How It Works
|
|
|
|
### Compression blocks
|
|
|
|
When the LLM calls the `compress` tool it provides one or more `{startId, endId, summary}` ranges. DCP:
|
|
|
|
1. Records the range as a `CompressionBlock` with start/end timestamps
|
|
2. On every `context` event, splices out the raw messages in that range
|
|
3. Injects a synthetic `[Compressed section: …]` user message containing the summary
|
|
4. Keeps the block state in the session so it survives restarts
|
|
|
|
Message IDs (`m001`, `m042`, etc.) and block IDs (`b1`, `b3`) are injected into every message in the context so the LLM can reference exact boundaries.
|
|
|
|
### Nudge types
|
|
|
|
| Nudge | Condition |
|
|
|---|---|
|
|
| **context-strong** | Above `maxContextPercent`, nudge counter ≥ `nudgeFrequency`, `nudgeForce = "strong"` |
|
|
| **context-soft** | Same as above with `nudgeForce = "soft"` |
|
|
| **iteration** | Between min/max percent AND ≥ `iterationNudgeThreshold` tool calls since last user message |
|
|
| **turn** | Between min/max percent, standard cadence |
|
|
|
|
### Deduplication
|
|
|
|
Two tool results share the same fingerprint (`toolName::JSON(sorted-args)`) if they were called with identical arguments. All but the last occurrence are replaced with a tombstone message.
|
|
|
|
### Error purging
|
|
|
|
Tool results that were errors are replaced with a tombstone after `purgeErrors.turns` user turns have passed, keeping the context clean of long-dead failure traces.
|
|
|
|
## Status indicator
|
|
|
|
A `DCP` badge is shown in the pi status bar. In manual mode it displays `DCP [manual]`.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
npx tsc --noEmit # type-check without emitting
|
|
```
|
|
|
|
The extension is loaded by pi via [jiti](https://github.com/unjs/jiti) so TypeScript is executed directly — no build step required for normal use.
|