pi-blackhole 0.4.7 → 0.4.9
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/README.md +162 -382
- package/dist/index.js +2432 -309
- package/dist/index.js.map +1 -1
- package/example-config.json +5 -2
- package/index.ts +6 -0
- package/package.json +3 -3
- package/src/commands/blackhole-export.ts +130 -0
- package/src/core/compaction-chain.ts +472 -0
- package/src/core/config-env.ts +9 -0
- package/src/core/summarize.ts +29 -7
- package/src/core/unified-config.ts +17 -0
- package/src/details.ts +123 -5
- package/src/hooks/before-compact.ts +139 -22
- package/src/hooks/compact-failed.ts +174 -0
- package/src/hooks/compaction-context.ts +28 -0
- package/src/om/compaction-trigger.ts +108 -16
- package/src/om/configure-overlay.ts +9 -0
- package/src/om/inline-compaction.ts +99 -31
- package/src/om/ledger/progress.ts +49 -1
- package/src/om/runtime.ts +27 -5
- package/src/om/tokens.ts +42 -2
- package/src/pi-base/blackhole-settings.ts +23 -0
- package/src/pi-base/settings/body.ts +2 -0
- package/src/pi-base/settings/render.ts +7 -5
- package/src/project-recall/corpus.ts +569 -0
- package/src/project-recall/dedup.ts +538 -0
- package/src/project-recall/format-export.ts +1000 -0
- package/src/project-recall/session-dir.ts +41 -0
package/README.md
CHANGED
|
@@ -1,106 +1,172 @@
|
|
|
1
1
|
# pi-blackhole
|
|
2
2
|
|
|
3
|
+
**Deterministic compaction + session-aware observational memory for [Pi](https://github.com/earendil-works/pi) — in one unified extension.**
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
**Algorithmic compaction + session-aware observational memory for [Pi](https://github.com/badlogic/pi-mono) — in one unified extension.**
|
|
6
|
-
|
|
7
|
-
Blackhole merges the best ideas from [pi-vcc](https://github.com/sting8k/pi-vcc) and [pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) into something that's become its own beast entirely. Deterministic compaction that costs nothing. A memory layer that survives compactions. Per-worker model fallback chains with persisted cooldowns. Manual flush mode. All configured from one JSON file.
|
|
8
|
-
|
|
9
|
-
> **Why this exists:** I liked both extensions but they fought each other — OM hooked into Pi's default compaction and blocked vcc from working. So I merged them, made them share a single hook and output, and added everything both were missing: fallback chains, cooldowns, a memory toggle, and a manual mode for people who want to control when context gets compressed.
|
|
10
|
-
>
|
|
11
|
-
> The codebase has since diverged heavily from both upstreams, but tries to keep up-to-date with any fixes from them.
|
|
12
|
-
|
|
13
|
-
📖 See [`CHANGELOG.md`](CHANGELOG.md) for release history.
|
|
14
|
-
⚙️ See [`CONFIG.md`](CONFIG.md) for the full configuration reference.
|
|
15
|
-
🔄 See [`MIGRATION-GUIDE.md`](MIGRATION-GUIDE.md) if upgrading from an older version.
|
|
16
|
-
📜 See [`OLD_CONFIG.md`](OLD_CONFIG.md) for the legacy config documentation.
|
|
5
|
+
`/blackhole` replaces Pi's LLM-based `/compact` with an algorithmic structural summary — fast, zero-cost. Three background workers (Observer, Reflector, Dropper) capture durable facts and decisions that survive across compactions. Per-worker model fallback chains with persisted cooldowns. Manual flush mode. One JSON file to configure it all.
|
|
17
6
|
|
|
18
7
|
---
|
|
19
8
|
|
|
20
|
-
##
|
|
9
|
+
## Install
|
|
21
10
|
|
|
22
11
|
```bash
|
|
23
|
-
#
|
|
12
|
+
# From npm (recommended)
|
|
24
13
|
pi install npm:pi-blackhole
|
|
25
14
|
|
|
26
15
|
# Or directly from GitHub
|
|
27
16
|
pi install git:github.com/k0valik/pi-blackhole
|
|
28
17
|
```
|
|
29
18
|
|
|
30
|
-
If you have standalone pi-vcc or pi-observational-memory installed, remove them first — they conflict and will prevent blackhole from
|
|
19
|
+
If you have standalone `pi-vcc` or `pi-observational-memory` installed, remove them first — they conflict and will prevent blackhole from loading:
|
|
31
20
|
|
|
32
21
|
```bash
|
|
33
22
|
pi uninstall npm / git:https://github.com/sting8k/pi-vcc
|
|
34
23
|
pi uninstall npm / git:https://github.com/elpapi42/pi-observational-memory
|
|
35
24
|
```
|
|
36
25
|
|
|
37
|
-
Then `/reload` or restart Pi.
|
|
26
|
+
Then `/reload` or restart Pi. The config file at `~/.pi/agent/pi-blackhole/pi-blackhole-config.json` is created with sensible defaults — no setup required for the default behavior. Config merges global → project → env → session (session is ephemeral). See **[`CONFIG.md`](CONFIG.md)** for tuning or run `/blackhole settings` to open the interactive overlay.
|
|
38
27
|
|
|
39
|
-
|
|
28
|
+
> **Want a guided setup?** Pass [`llms.txt`](llms.txt) to your agent — it will walk you through the interview, including picking cheap fallback models for your providers.
|
|
40
29
|
|
|
41
|
-
|
|
30
|
+
---
|
|
42
31
|
|
|
43
|
-
|
|
32
|
+
## What it does
|
|
44
33
|
|
|
45
|
-
|
|
34
|
+
Long engineering sessions degrade. Pi's native `/compact` calls an LLM to write a free-form prose summary — then compacts that summary, then compacts the next. After a few cycles, load-bearing details vanish: why a decision was made, which approaches were rejected, what the user clarified early on. The session is still alive; the agent has stopped carrying the real context.
|
|
46
35
|
|
|
47
|
-
|
|
36
|
+
`pi-blackhole` solves this in two complementary ways:
|
|
48
37
|
|
|
49
|
-
|
|
38
|
+
- **Algorithmic compaction** — a deterministic, zero-cost `compile()` pipeline extracts structured sections (goal, files, commits, preferences, brief transcript) and replaces the old conversation with one compact block. No LLM is called for compaction itself.
|
|
39
|
+
- **Observational memory** — three background workers (Observer → Reflector → Dropper) run during the session, capturing timestamped facts and distilling durable reflections in a session ledger that survives every compaction.
|
|
50
40
|
|
|
51
|
-
|
|
41
|
+
Both halves share a single hook and a single output. Together they keep the agent's context sharp across arbitrarily long sessions — without the cost, drift, or erosion of repeated LLM-based summarization.
|
|
52
42
|
|
|
43
|
+
---
|
|
53
44
|
|
|
45
|
+
## ✨ What's new
|
|
54
46
|
|
|
55
|
-
|
|
47
|
+
> **Latest release: [0.4.8](CHANGELOG.md#048---2026-08-23)**
|
|
48
|
+
>
|
|
49
|
+
> - **Append compaction mode** (`compactionSummaryMode: "append"`) — better prompt caching - keep every auto-compaction summary as an immutable segment visible to the model (`S1 | S2 | …`) instead of rewriting a single summary. `/blackhole` rebases the chain. Opt-in.
|
|
50
|
+
> - **Mid-run auto-compaction** (`midRunCompaction: "resume"` | `"pause"`) — **good for goal/task** opt into transparent compaction during long tool loops without interrupting the agent. Default is `"off"`.
|
|
51
|
+
> - **`/blackhole-export` — distilled project-memory export** ([#65](https://github.com/k0valik/pi-blackhole/pull/65)) — scans all project sessions + pending buffers, fuzzy-dedupes, and writes one import-ready Markdown (`Reflections → Critical → High → Medium → Low`) with topic badges and orphan-gated pending. `out:<path>.md` supported.
|
|
52
|
+
> - **Robust compaction-failure handling** — unified `session_compact_failed` (pi >=0.84.3) with correct attribution, overflow-retry visibility, and noise filtering; plus bundled-CLI `AgentSession` resolution so inline compaction works from `dist/bundle/cli.js` ([#62](https://github.com/k0valik/pi-blackhole/pull/62)).
|
|
56
53
|
|
|
54
|
+
See [`CHANGELOG.md`](CHANGELOG.md) for the full history.
|
|
57
55
|
|
|
56
|
+
### ⚠️ Upcoming change
|
|
58
57
|
|
|
58
|
+
> **Default compaction thresholds will become model-context-window-aware** in an upcoming release. Instead of static absolute tokens (`compactAfterTokens: 81000`), default thresholds will derive from your model's effective context window — keeping the same approximate cadence regardless of model size. Existing explicitly-set values will continue to be respected verbatim. If you're using the defaults, no action is needed; the migration is automatic.
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
62
|
## Commands
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
| Command | Description & Options |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `/blackhole` | Manual compact — deterministic structural summary |
|
|
67
|
+
| `/blackhole settings` | Open the configuration overlay *(Alias: `/blackhole configure`)* |
|
|
68
|
+
| `/blackhole cleanup` | Remove orphaned pending files |
|
|
69
|
+
| `/blackhole om-off` | Disable observational memory |
|
|
70
|
+
| `/blackhole om-on` | Enable observational memory |
|
|
71
|
+
| `/blackhole-memory` | Memory pipeline status & token counters *(Same as `/blackhole-memory status`)* |
|
|
72
|
+
| `/blackhole-memory view` | Show visible observations and reflections (after compaction trimming), copied to clipboard |
|
|
73
|
+
| `/blackhole-memory full` | Show **all** recorded memory (including dropped observations), copied to clipboard |
|
|
74
|
+
| `/blackhole-recall <query>` | Search session history. Supports `page:N`, `scope:all`, `mode:file|touched`, regex *(Also available to agent as `recall` tool)* |
|
|
75
|
+
| `/blackhole-export` | Export distilled project memory (observations/reflections across past sessions + pending buffers) to import-ready markdown *(Options: `out:<path>.md`)* |
|
|
76
|
+
|
|
77
|
+
All commands work regardless of `compaction` mode — only *when* auto-compaction fires changes. See [Compaction modes](#compaction-modes) below.
|
|
78
|
+
|
|
79
|
+
### The `recall` tool (agent-facing)
|
|
80
|
+
|
|
81
|
+
The agent gets one unified `recall` tool that handles every form of historical lookup. Searches read the raw session file directly, bypassing compaction.
|
|
82
|
+
|
|
83
|
+
| Input | What it does |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `[12-char hex]` | Recover source evidence for a specific observation or reflection ID from the session ledger. |
|
|
86
|
+
| `#N` | Expand a session entry by index (show full content, not truncated). |
|
|
87
|
+
| `#N:path` | Drill-down into file content from a tool call (e.g. `#42:auth.ts` shows first 30 lines; `#42:auth.ts:30` shows the next 30; `#42:auth.ts:full` shows everything). |
|
|
88
|
+
| Free text | BM25-ranked search across transcript and/or file content. Rare terms weighted higher. |
|
|
89
|
+
| `mode:file` | Search only write/edit file content. |
|
|
90
|
+
| `mode:touched` | Aggregate all files written/edited across the session, grouped by path. |
|
|
91
|
+
| Regex | Pattern search (e.g. `fork.*pi-vcc`, `hook\|inject`). |
|
|
92
|
+
| `scope:all` | Search across all session lineages (default: active lineage only). |
|
|
93
|
+
|
|
94
|
+
When the agent expands a session entry (`#N`), related observations and reflections from the session ledger are automatically shown alongside the expanded content — so the agent gets the raw transcript *and* the durable fact layer in one call.
|
|
95
|
+
|
|
96
|
+
The `/blackhole-recall` command exposes the same engine to the user. Results are shown as a collapsible message and auto-fed to the agent as context.
|
|
74
97
|
|
|
75
98
|
---
|
|
76
99
|
|
|
77
|
-
##
|
|
100
|
+
## Compaction modes
|
|
101
|
+
|
|
102
|
+
Two modes, one shared goal: keep your agent's context sharp without manual housekeeping. (`compaction: "off"` is a third escape hatch that hands everything back to Pi.)
|
|
78
103
|
|
|
79
|
-
|
|
104
|
+
| | Auto (default) | Manual (`compaction: "manual"`) | Off (`compaction: "off"`) |
|
|
105
|
+
|---|---|---|---|
|
|
106
|
+
| Workers run? | Yes | Yes | Yes (unless `memory: false`) |
|
|
107
|
+
| Observations go to | Conversation markers (invisible in TUI) | Per-session disk buffers | Conversation markers |
|
|
108
|
+
| Auto-compact on `agent_end` | Yes — blackhole fires at `compactAfterTokens` | No | No (Pi handles it) |
|
|
109
|
+
| `/compact` (Pi built-in) | Replaced by blackhole | Pi handles | Pi handles |
|
|
110
|
+
| `/blackhole` | Optional | **Required** to flush + compact | Optional, but works |
|
|
111
|
+
| Use case | "Install and forget" | "I want to control when context gets compressed" | "Let Pi handle it, but I want `/blackhole` when I need it" |
|
|
80
112
|
|
|
81
|
-
|
|
113
|
+
Manual mode is the maintainer's daily driver: workers still run, but observations accumulate in `<sessionId>-pending.json` files instead of cluttering the conversation. `/blackhole` flushes the buffer, runs algorithmic compaction, and injects durable reflections in one shot.
|
|
82
114
|
|
|
83
|
-
|
|
115
|
+
`compaction: "off"` + `memory: false` (or `PI_BLACKHOLE_PASSIVE=true`) completely disables all background workers and blackhole's auto-compaction — useful for debugging or comparing against Pi's native path. Explicit `/blackhole` still works in this mode.
|
|
84
116
|
|
|
85
|
-
|
|
86
|
-
- **pi-observational-memory** captures timestamped observations and durable reflections in a session ledger that survives across compactions. But its compaction path still calls an LLM — costing money and risking drift on every compact.
|
|
117
|
+
### How does `/blackhole` compare to `/compact`?
|
|
87
118
|
|
|
88
|
-
|
|
119
|
+
- `/compact` calls an LLM to write a free-form summary — costly, lossy, no memory layer.
|
|
120
|
+
- `/blackhole` uses algorithmic section extraction (goals, files, commits, preferences…) **plus** injects observations and reflections from the session ledger. No LLM is involved in the compaction itself. Fast, deterministic, memory-preserving - the observational memory pipeline's arrived results apply instantly on compaction.
|
|
121
|
+
|
|
122
|
+
`/blackhole` is essentially a single `/compact` that just works — especially in manual mode.
|
|
89
123
|
|
|
90
124
|
---
|
|
91
125
|
|
|
92
126
|
## How it works
|
|
93
127
|
|
|
94
|
-
When
|
|
128
|
+
When `/blackhole` fires (manually or via the auto-trigger), two things happen in one shot:
|
|
95
129
|
|
|
96
|
-
1. **The vcc pipeline** analyzes the transcript tail and produces a structured summary: session goal, file changes, commits, outstanding blockers, user preferences, and a rolling brief transcript.
|
|
130
|
+
1. **The vcc pipeline** analyzes the transcript tail and produces a structured summary: session goal, file changes, commits, outstanding blockers, user preferences, and a rolling brief transcript. Deterministic — same input always produces the same output.
|
|
97
131
|
2. **Observational memory injection** renders accumulated observations and reflections from the session ledger and appends them below the summary.
|
|
98
132
|
|
|
99
133
|
The agent receives a deterministic recap of recent work *plus* durable facts from the full session history — in a single replacement block. No LLM was called for the compaction itself.
|
|
100
134
|
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Quick start config
|
|
138
|
+
|
|
139
|
+
Defaults target ~128k context models and work out of the box — no tuning required. To keep costs low, set cheap models for the background workers (the only required change for most setups):
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"observerModel": { "provider": "openrouter", "id": "qwen/qwen3-next-80b-a3b-instruct:free" },
|
|
144
|
+
"reflectorModel": { "provider": "cerebras", "id": "gpt-oss-120b" },
|
|
145
|
+
"dropperModel": { "provider": "cerebras", "id": "gpt-oss-120b" }
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Fallbacks (optional): each worker tries `stageModel → stageFallbacks → base model → session model` (skipping cooled-down models). By default the workers **do not** fall back to your session model — this avoids surprise cost and cache busting. Enable it with `sessionFallback: true` (default) or set `model` as a shared fallback. See [`CONFIG.md` → Model Configuration](CONFIG.md#model-configuration).
|
|
150
|
+
|
|
151
|
+
Config file: **`~/.pi/agent/pi-blackhole/pi-blackhole-config.json`**
|
|
152
|
+
|
|
153
|
+
Full reference — every key, default, and env override — lives in:
|
|
154
|
+
|
|
155
|
+
- 📘 **[`CONFIG.md`](CONFIG.md)** — authoritative config reference. Start here for tuning.
|
|
156
|
+
- 🤖 **[`llms.txt`](llms.txt)** — agent-facing interview. Pass it to your agent for a guided setup.
|
|
157
|
+
- 📦 **[`example-config.json`](example-config.json)** — annotated example with fallback rationale and `thinking` levels.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Demo
|
|
162
|
+
|
|
163
|
+
`/blackhole` collapses ~143k tokens of conversation into a ~6.3k structured summary (YMMV based on your settings). `/blackhole-memory` shows pipeline status. `/blackhole-recall` searches history — the agent can do the same via its `recall` tool.
|
|
164
|
+
|
|
165
|
+
https://github.com/user-attachments/assets/a7dd804d-6aca-4bdb-8b6e-0dd779363a43
|
|
166
|
+
|
|
101
167
|
### The three memory workers
|
|
102
168
|
|
|
103
|
-
Three background workers (separate LLM calls) run automatically during the session
|
|
169
|
+
Three background workers (separate LLM calls) run automatically during the session when `memory: true` (the default):
|
|
104
170
|
|
|
105
171
|
- **Observer** — reads conversation since the last observation marker and extracts timestamped facts: events, decisions, preferences. Input is capped to `observerChunkMaxTokens` newest-first to prevent context blowup on long sessions. Runs most frequently.
|
|
106
172
|
- **Reflector** — distills new observations into durable reflections: stable facts, patterns, and constraints that survive future compactions. Runs less often.
|
|
@@ -110,25 +176,22 @@ Three background workers (separate LLM calls) run automatically during the sessi
|
|
|
110
176
|
[Conversation turn] ──> (accumulated tokens >= observeAfterTokens)
|
|
111
177
|
│
|
|
112
178
|
v
|
|
113
|
-
1. OBSERVER
|
|
114
|
-
(extracts timestamped observations via agent loop)
|
|
179
|
+
1. OBSERVER (extracts timestamped observations)
|
|
115
180
|
│
|
|
116
181
|
v
|
|
117
|
-
2. REFLECTOR
|
|
118
|
-
(synthesizes durable reflections via agent loop)
|
|
182
|
+
2. REFLECTOR (synthesizes durable reflections)
|
|
119
183
|
│
|
|
120
184
|
v
|
|
121
|
-
3. DROPPER
|
|
122
|
-
(prunes low-value observations, keeps reflections)
|
|
185
|
+
3. DROPPER (prunes low-value observations)
|
|
123
186
|
```
|
|
124
187
|
|
|
125
188
|
Each worker uses an `agentLoop` with tool-calling capabilities — they don't just make a single LLM call. The observer, for example, can call `record_observations` multiple times per run to work through a chunk incrementally.
|
|
126
189
|
|
|
127
|
-
### Graceful degradation
|
|
128
|
-
|
|
129
190
|
If any stage fails (model error, rate limit, timeout), remaining stages are skipped and the full pipeline retries on the next `agent_start` or `turn_end`. A 30-second retry gate prevents hammering failing APIs. Within each stage, the runtime tries all configured fallback models before giving up — each failed model is cooled down and skipped in subsequent attempts.
|
|
130
191
|
|
|
131
|
-
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## What the agent sees after compaction
|
|
132
195
|
|
|
133
196
|
After compaction, the agent sees something like this (sections appear only when relevant — a session with no git commits won't show `[Commits]`):
|
|
134
197
|
|
|
@@ -159,8 +222,6 @@ Fix the auth bug...
|
|
|
159
222
|
Root cause is a missing token refresh...
|
|
160
223
|
...transcript continues...
|
|
161
224
|
|
|
162
|
-
---
|
|
163
|
-
|
|
164
225
|
---
|
|
165
226
|
The conversation before this point has been compacted into the summary above.
|
|
166
227
|
Details not captured here — exact code, error messages, file paths — are only recoverable via `recall`.
|
|
@@ -174,322 +235,14 @@ Use `recall` to search the session history. Do not redo work already completed.
|
|
|
174
235
|
[b2c3d4e5f6a1] 2026-05-23 [medium] GraphQL migration completed; user confirmed working.
|
|
175
236
|
|
|
176
237
|
----
|
|
177
|
-
Bracketed ids in reflections and observations connect to their source session entries.
|
|
238
|
+
Bracketed ids in reflections and observations connect to their source session entries.
|
|
239
|
+
These are condensed memories from earlier in this session.
|
|
178
240
|
When entries conflict, the most recent observation reflects the latest known state.
|
|
179
|
-
Use `recall` with an id to retrieve original context
|
|
180
|
-
When exact source context is needed for precision or traceability, use the `recall` tool with the relevant observation or reflection id. This is especially useful when a reflection materially affects a decision or is too compressed to continue confidently.
|
|
241
|
+
Use `recall` with an id to retrieve original context.
|
|
181
242
|
----
|
|
182
243
|
```
|
|
183
244
|
|
|
184
|
-
> **Note:** The OM injection format uses `## Reflections` and `## Observations` Markdown headers followed by a brief footer. Each observation and reflection has a 12-char hex identifier
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Compaction modes
|
|
189
|
-
|
|
190
|
-
Two modes, one shared goal: keep your agent's context sharp without manual housekeeping.
|
|
191
|
-
|
|
192
|
-
- **Auto mode (default):** install and forget. Workers run, observations are appended as invisible conversation markers, compaction fires automatically when tokens exceed threshold.
|
|
193
|
-
- **Manual mode (`compaction: "manual"` — the maintainer's daily driver):** same workers, same pipeline. But observations go to per-session disk buffers and compaction only happens when you run `/blackhole`. Cleaner conversation, manual schedule.
|
|
194
|
-
|
|
195
|
-
The tradeoff is simplicity vs cleanliness:
|
|
196
|
-
|
|
197
|
-
| | Auto (default) | Manual (`compaction: "manual"`) |
|
|
198
|
-
|---|---|---|
|
|
199
|
-
| Workers run? | Yes | Yes |
|
|
200
|
-
| Observations go to | Conversation markers (invisible in TUI) | Disk (`<sessionId>-pending.json`) |
|
|
201
|
-
| Observations accumulate across runs | Branch markers (replaced each cycle) | Pending batches accumulated — `/blackhole-memory` shows pending counts |
|
|
202
|
-
| Auto-compact on `agent_end` | Yes | No |
|
|
203
|
-
| `/blackhole` | Optional — use it whenever you want | Required to flush + compact |
|
|
204
|
-
| Conversation history | OM marker entries between turns (they exist but don't clutter the display) | Clean — nothing between turns |
|
|
205
|
-
| Use case | "I don't want to think about it" | "I want to control when context gets compressed" |
|
|
206
|
-
|
|
207
|
-
**Does `/blackhole` work like a single `/compact` that Just Works?**
|
|
208
|
-
|
|
209
|
-
Yes, that's exactly the idea, especially in manual mode. When you feel context is getting full or accuracy is slipping, type `/blackhole`. It flushes any accumulated observations from disk, runs algorithmic vcc compaction (zero LLM cost), and injects your durable reflections into the replacement block. One command, everything gets compressed while keeping your session memory alive.
|
|
210
|
-
|
|
211
|
-
The difference from Pi's built-in `/compact`:
|
|
212
|
-
- `/compact` calls an LLM to write a free-form summary — costly, lossy, no memory layer.
|
|
213
|
-
- `/blackhole` uses algorithmic section extraction (goals, files, commits, preferences...) plus injects observations/reflections from the session ledger. No LLM involved in the compaction itself. Fast, deterministic, memory-preserving.
|
|
214
|
-
|
|
215
|
-
### Fully disabled
|
|
216
|
-
|
|
217
|
-
Set `compaction: "off"` and `memory: false` (or the environment variable `PI_BLACKHOLE_PASSIVE=true` which sets both) to completely disable all background workers and blackhole's auto-compaction trigger. Pi handles auto-compaction normally. Explicit `/blackhole` still uses blackhole's pipeline. This is useful for debugging or if you want manual-only blackhole involvement.
|
|
218
|
-
|
|
219
|
-
### Without observational memory (vcc-only)
|
|
220
|
-
|
|
221
|
-
Set `memory: false` or run `/blackhole om-off` for pure vcc compaction — no background workers, no memory injection. The compaction still uses the algorithmic vcc pipeline (not Pi's LLM-based compaction). Re-enable with `/blackhole om-on` or setting `memory: true`.
|
|
222
|
-
|
|
223
|
-
This is a lighter alternative to `compaction: "off"`: workers are off but blackhole's compaction engine still handles compaction.
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## Commands
|
|
228
|
-
|
|
229
|
-
| Command | What it does |
|
|
230
|
-
|---|---|
|
|
231
|
-
| `/blackhole` | Compact the conversation. Subcommands: `configure` (settings overlay), `om-off` / `om-on` toggle observational memory. |
|
|
232
|
-
| `/blackhole-memory` (or `status`) | Pipeline status: token progress, observation/reflection counts, pending data, last errors |
|
|
233
|
-
| `/blackhole-memory view` | Show visible observations and reflections (after compaction trimming), copied to clipboard |
|
|
234
|
-
| `/blackhole-memory full` | Show ALL recorded memory (including dropped observations), copied to clipboard |
|
|
235
|
-
| `/blackhole-recall <query>` | Search session history. Supports `page:N`, `scope:all`, `mode:file|transcript|touched` |
|
|
236
|
-
|
|
237
|
-
## Tools
|
|
238
|
-
|
|
239
|
-
The agent gets a unified `recall` tool that handles three types of input:
|
|
240
|
-
|
|
241
|
-
| Input | What it does |
|
|
242
|
-
|---|---|
|
|
243
|
-
| `[12-char hex]` | Recover source evidence for a specific observation or reflection ID from the session ledger |
|
|
244
|
-
| `#N` | Expand a session entry by index (show full content) |
|
|
245
|
-
| `#N:path` | Drill-down into file content from a tool call (e.g. `#42:auth.ts` shows first 30 lines; `#42:auth.ts:30` shows next 30; `#42:auth.ts:full` shows everything) |
|
|
246
|
-
| Free text | BM25-ranked OR search across transcript and/or file content. Rare terms weighted higher. |
|
|
247
|
-
| `mode:file` | Search only write/edit file content |
|
|
248
|
-
| `mode:touched` | Aggregate all files written/edited, grouped by path with entry indices |
|
|
249
|
-
| Regex | Pattern search (e.g. `fork.*pi-vcc`, `hook|inject`) |
|
|
250
|
-
| `scope:all` | Search across all session lineages, not just the active one |
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Configuration
|
|
255
|
-
|
|
256
|
-
All settings in a single JSON file: **`~/.pi/agent/pi-blackhole/pi-blackhole-config.json`** — auto-created with defaults on first startup. See [`CONFIG.md`](CONFIG.md) for the full reference with detailed explanations for every knob. An annotated example config is at [`example-config.json`](example-config.json).
|
|
257
|
-
|
|
258
|
-
**Invalid JSON protection:** If the config file has a syntax error (trailing comma, partial write, sync conflict), the overlay (`/blackhole configure`) shows a red error banner and blocks save to prevent wiping your model configs. A yellow warning is also shown in the TUI. Fix the JSON directly in the file, then reopen the overlay.
|
|
259
|
-
|
|
260
|
-
**Overlay reload:** Changes saved via `/blackhole configure` take effect immediately — no session restart needed. The runtime reloads config from disk after every successful overlay save.
|
|
261
|
-
|
|
262
|
-
Quick start — just set custom models (if you want):
|
|
263
|
-
|
|
264
|
-
```json
|
|
265
|
-
{
|
|
266
|
-
"observerModel": { "provider": "openrouter", "id": "qwen/qwen3-next-80b-a3b-instruct:free" },
|
|
267
|
-
"reflectorModel": { "provider": "cerebras", "id": "gpt-oss-120b" },
|
|
268
|
-
"dropperModel": { "provider": "cerebras", "id": "gpt-oss-120b" }
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Everything else has sensible defaults.
|
|
273
|
-
|
|
274
|
-
### Settings at a glance
|
|
275
|
-
|
|
276
|
-
| Setting | Default | What it controls |
|
|
277
|
-
|---|---|---|
|
|
278
|
-
| `compaction` | `"auto"` | When compaction triggers: `"auto"` (blackhole auto-fires), `"manual"` (only `/blackhole`), `"off"` (Pi handles auto + `/compact`, `/blackhole` still works) |
|
|
279
|
-
| `compactionEngine` | `"blackhole"` | Which engine handles auto-compaction: `"blackhole"` or `"pi-default"`. Only meaningful when `compaction: "auto"` — for `"manual"`/`"off"` the hook lets Pi handle everything except `/blackhole` |
|
|
280
|
-
| `tailBehavior` | `"minimal"` | How much stays visible after compaction: `"minimal"` (last user message only, default) or `"pi-default"` (gentle, ~20k tokens). Both `/blackhole` and auto-triggered default to `"minimal"`; set explicitly to opt into gentler cut |
|
|
281
|
-
| `midRunCompaction` | `"off"` | `"resume"` *(experimental)* opts into transparent compaction during long tool loops without replacing the active run; `"pause"` interrupts, compacts, and stops; `"off"` only checks when the run ends. Transparent mode fails closed on unsupported Pi internals. |
|
|
282
|
-
| `memory` | `true` | `false` = OM workers off + no memory injection (compaction still runs) |
|
|
283
|
-
| `model` | — | Base fallback model for all workers (last resort before session model) |
|
|
284
|
-
| `observerModel` / `observerFallbackModels` | — / `[]` | Primary + fallback models for observer (extracts facts) |
|
|
285
|
-
| `reflectorModel` / `reflectorFallbackModels` | — / `[]` | Primary + fallback models for reflector (synthesizes reflections) |
|
|
286
|
-
| `dropperModel` / `dropperFallbackModels` | — / `[]` | Primary + fallback models for dropper (prunes observations) |
|
|
287
|
-
| `sessionFallback` | `true` | When false, skip session model fallback when all OM model candidates are exhausted. Default true for backward compatibility. |
|
|
288
|
-
| *(per model)* `thinking` | `"low"` | Thinking/reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh` |
|
|
289
|
-
| *(per model)* `cooldownHours` | `1` | How long to skip this model after a retryable error |
|
|
290
|
-
| *(per model)* `contextWindow` | *(inherited from Pi)* | Override context window for this model. If unset, inherits from Pi's model registry. When set, the OM pipeline checks if the estimated input fits before calling the model — if not, the next fallback is tried. |
|
|
291
|
-
| `observeAfterTokens` | `15000` | Min accumulated tokens before observer runs |
|
|
292
|
-
| `reflectAfterTokens` | `25000` | Min accumulated tokens before reflector + dropper run |
|
|
293
|
-
| `compactAfterTokens` | `81000` | Auto-compaction threshold (when `compaction: "auto"`) |
|
|
294
|
-
| `observerChunkMaxTokens` | `40000` | Max observer input per run (newest-first) |
|
|
295
|
-
| `observerPreambleMaxTokens` | `0` (auto) | Preamble cap for observer in `compaction: "manual"` mode (auto = 30% of chunk) |
|
|
296
|
-
| `observationsPoolMaxTokens` | `20000` | Max active observation pool before dropper prunes |
|
|
297
|
-
| `observationsPoolTargetTokens` | `10000` | Target size dropper aims for after pruning (derived: half of pool max) |
|
|
298
|
-
| `reflectorInputMaxTokens` | `80000` | Max reflector input budget |
|
|
299
|
-
| `dropperInputMaxTokens` | `80000` | Max dropper input budget |
|
|
300
|
-
| `dropperPressureThreshold` | `0.70` | Fraction of `reflectorInputMaxTokens` at which dropper runs even without new data (pressure relief valve) |
|
|
301
|
-
| `agentMaxTurns` | `16` | Max agent-loop turns per worker per run |
|
|
302
|
-
| `providerIdleTimeoutMs` | unset | Body-idle timeout for background provider streams (ms); `0` = disabled, unset = inherit pi's default |
|
|
303
|
-
| `debug` | `false` | Pre-compaction snapshot to `/tmp/pi-blackhole-debug.json` |
|
|
304
|
-
| `debugLog` | `false` | Continuous JSONL debug log to `~/.pi/agent/pi-blackhole/debug.ndjson` |
|
|
305
|
-
|
|
306
|
-
**Environment override:** `PI_BLACKHOLE_PASSIVE=true` sets `compaction: "off"` + `memory: false` without touching the config file. Also accepts legacy `PI_VCC_OM_PASSIVE` / `PI_OBSERVATIONAL_MEMORY_PASSIVE`.
|
|
307
|
-
|
|
308
|
-
### Configuration presets
|
|
309
|
-
|
|
310
|
-
The defaults above target a **medium-context** setup (~128k context window, e.g. GPT-4o, Claude Sonnet).
|
|
311
|
-
Paste the appropriate block into your config to match your main session model's context size.
|
|
312
|
-
|
|
313
|
-
#### Low context (~32k-64k — older models, fast budget models)
|
|
314
|
-
|
|
315
|
-
```json
|
|
316
|
-
{
|
|
317
|
-
"observeAfterTokens": 5000,
|
|
318
|
-
"reflectAfterTokens": 10000,
|
|
319
|
-
"compactAfterTokens": 30000,
|
|
320
|
-
"observerChunkMaxTokens": 15000,
|
|
321
|
-
"observerPreambleMaxTokens": 0,
|
|
322
|
-
"observationsPoolMaxTokens": 8000,
|
|
323
|
-
"reflectorInputMaxTokens": 30000,
|
|
324
|
-
"dropperInputMaxTokens": 30000,
|
|
325
|
-
"dropperPressureThreshold": 0.70
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
#### Medium context (~128k — GPT-4o, Claude Sonnet, Gemini Pro; this is the default)
|
|
330
|
-
|
|
331
|
-
These are the built-in defaults. If you reset your config, these are what you get:
|
|
332
|
-
|
|
333
|
-
```json
|
|
334
|
-
{
|
|
335
|
-
"observeAfterTokens": 15000,
|
|
336
|
-
"reflectAfterTokens": 25000,
|
|
337
|
-
"compactAfterTokens": 81000,
|
|
338
|
-
"observerChunkMaxTokens": 40000,
|
|
339
|
-
"observerPreambleMaxTokens": 0,
|
|
340
|
-
"observationsPoolMaxTokens": 20000,
|
|
341
|
-
"reflectorInputMaxTokens": 80000,
|
|
342
|
-
"dropperInputMaxTokens": 80000,
|
|
343
|
-
"dropperPressureThreshold": 0.70
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
#### High context (~200k+ — Claude Opus, Gemini Ultra, large local models)
|
|
348
|
-
|
|
349
|
-
```json
|
|
350
|
-
{
|
|
351
|
-
"observeAfterTokens": 20000,
|
|
352
|
-
"reflectAfterTokens": 40000,
|
|
353
|
-
"compactAfterTokens": 180000,
|
|
354
|
-
"observerChunkMaxTokens": 80000,
|
|
355
|
-
"observerPreambleMaxTokens": 0,
|
|
356
|
-
"observationsPoolMaxTokens": 40000,
|
|
357
|
-
"reflectorInputMaxTokens": 160000,
|
|
358
|
-
"dropperInputMaxTokens": 160000,
|
|
359
|
-
"dropperPressureThreshold": 0.70
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
**What to tune first:** `compactAfterTokens` should be significantly below your model's total context window — aim for ~60-70%. If the agent loses context before compaction fires, lower it. If compaction fires too often and breaks flow, raise it. The other thresholds scale proportionally.
|
|
364
|
-
|
|
365
|
-
### Tip: comments in config
|
|
366
|
-
|
|
367
|
-
The config preserves unknown keys when loaded, so you can add `_comment` or `_notes` fields to document your choices inline. They're ignored by the parser.
|
|
368
|
-
|
|
369
|
-
```json
|
|
370
|
-
{
|
|
371
|
-
"_comment": "Tuned for my Cerebras + OpenRouter free model setup",
|
|
372
|
-
"observerModel": { "provider": "openrouter", "id": "qwen/qwen3-next-80b-a3b-instruct:free", "thinking": "low" }
|
|
373
|
-
}
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
**Note:** The `/blackhole configure` overlay only manages the keys it knows about. All other keys (including `observerModel`, `reflectorModel`, `dropperModel`, and their fallback arrays) are preserved on save when the file has valid JSON. If the file has invalid JSON, save is blocked entirely — the overlay will not overwrite the file.
|
|
377
|
-
|
|
378
|
-
---
|
|
379
|
-
|
|
380
|
-
## Model fallback chains
|
|
381
|
-
|
|
382
|
-
Each worker has a primary model and an ordered fallback list. On any error — rate limit, timeout, API failure, 5xx — the failed model is cooled down and the next candidate is tried. If all candidates are exhausted, the pipeline aborts and retries on the next trigger event. The session model is always the last resort and is never cooled down.
|
|
383
|
-
|
|
384
|
-
```
|
|
385
|
-
[Worker fails: 429 / timeout / 5xx / connection error]
|
|
386
|
-
│
|
|
387
|
-
v
|
|
388
|
-
Add model to cooldown list
|
|
389
|
-
(persisted to pi-blackhole-cooldown.json)
|
|
390
|
-
│
|
|
391
|
-
v
|
|
392
|
-
Try next fallback candidate
|
|
393
|
-
│
|
|
394
|
-
v
|
|
395
|
-
[All candidates exhausted?]
|
|
396
|
-
│ │
|
|
397
|
-
yes no ──> try next
|
|
398
|
-
│
|
|
399
|
-
v
|
|
400
|
-
Fall back to session model (never cooled down)
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
Cooldowns survive Pi restarts — they're persisted to `~/.pi/agent/pi-blackhole/pi-blackhole-cooldown.json`. Each entry records the model identifier, the triggering error, which stage failed, and the expiry timestamp.
|
|
404
|
-
|
|
405
|
-
### Resolution order
|
|
406
|
-
|
|
407
|
-
For each stage, the runtime builds a candidate list from:
|
|
408
|
-
|
|
409
|
-
1. **Primary stage model** (`observerModel`, `reflectorModel`, `dropperModel`)
|
|
410
|
-
2. **Stage fallback models** (`observerFallbackModels`, etc.) — tried in order
|
|
411
|
-
3. **Base model** (`model` — shared across all workers)
|
|
412
|
-
4. **Session model** (the model used for your main conversation — always the last resort)
|
|
413
|
-
|
|
414
|
-
Models with active cooldowns are transparently skipped. The runtime tries up to 10 model resolutions per stage before giving up entirely.
|
|
415
|
-
|
|
416
|
-
### Example: full resolution chain
|
|
417
|
-
|
|
418
|
-
With a fully configured setup:
|
|
419
|
-
|
|
420
|
-
```
|
|
421
|
-
Observer: qwen3-next-80b (openrouter) → gemma4:31b-cloud (ollama) → gemma-4-31b-it:free (openrouter) → base model → session model
|
|
422
|
-
Reflector: gpt-oss-120b (cerebras) → glm-4.7 (z.ai) → gpt-oss-120b:free (openrouter) → base model → session model
|
|
423
|
-
Dropper: gpt-oss-120b (cerebras) → glm-4.7 (z.ai) → gpt-oss-120b:free (openrouter) → base model → session model
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
### Per-model thinking levels
|
|
427
|
-
|
|
428
|
-
Each model config supports a `thinking` field that controls reasoning effort:
|
|
429
|
-
|
|
430
|
-
```json
|
|
431
|
-
{
|
|
432
|
-
"observerModel": {
|
|
433
|
-
"provider": "openrouter",
|
|
434
|
-
"id": "qwen/qwen3-next-80b-a3b-instruct:free",
|
|
435
|
-
"thinking": "low", ← reasoning effort for this specific model
|
|
436
|
-
"cooldownHours": 12 ← custom cooldown duration
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
Valid values: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Not all models support every level.
|
|
442
|
-
|
|
443
|
-
### Retryable error detection
|
|
444
|
-
|
|
445
|
-
The runtime uses a regex to detect retryable errors — it looks for patterns like `rate limit`, `429`, `5xx`, `timeout`, `service unavailable`, `connection error`, `websocket closed`, etc. Non-retryable errors (auth failures, invalid model IDs) immediately skip that candidate and move to the next.
|
|
446
|
-
|
|
447
|
-
### 30-second retry gate
|
|
448
|
-
|
|
449
|
-
After any stage fails completely, the pipeline waits 30 seconds before attempting another consolidation run. This prevents rapid retry loops that would waste API calls on the same failing models.
|
|
450
|
-
|
|
451
|
-
---
|
|
452
|
-
|
|
453
|
-
## Recall
|
|
454
|
-
|
|
455
|
-
Pi's default compaction discards old messages permanently — after compaction, the agent only sees the summary. Blackhole preserves searchable history through two surfaces.
|
|
456
|
-
|
|
457
|
-
### `recall` tool (agent-facing)
|
|
458
|
-
|
|
459
|
-
The agent gets one unified tool that searches session history, expands entries, drills into file content, and looks up observational memory. Searches read the raw session file directly, bypassing compaction.
|
|
460
|
-
|
|
461
|
-
| Input | What it does |
|
|
462
|
-
|---|---|
|
|
463
|
-
| `[12-char hex]` | Recover source evidence for an observation or reflection ID from the session ledger |
|
|
464
|
-
| `#N` | Expand a session entry by index (show full content, not truncated) |
|
|
465
|
-
| `#N:path` | Drill-down into file content from a tool call (e.g. `#42:auth.ts` shows first 30 lines; `#42:auth.ts:30` shows next 30; `#42:auth.ts:full` shows everything) |
|
|
466
|
-
| Free text | BM25-ranked OR search across transcript + file indicators. Rare terms weighted higher. |
|
|
467
|
-
| `mode:file` | Search only write/edit file content |
|
|
468
|
-
| `mode:touched` | Aggregate all files written/edited across the session, grouped by path with entry indices |
|
|
469
|
-
| Regex | Pattern search (e.g. `fork.*pi-vcc`, `hook\|inject`) |
|
|
470
|
-
| `scope:all` | Search across all session lineages (default: active lineage only) |
|
|
471
|
-
|
|
472
|
-
**OM coupling:** When expanding session entries (`#N`), the tool automatically looks up related observations and reflections from the session ledger. If any of your expanded entries are referenced as source evidence by an observation, those observations are shown alongside the expanded content.
|
|
473
|
-
|
|
474
|
-
### `/blackhole-recall` command (user-facing)
|
|
475
|
-
|
|
476
|
-
Results are shown as a collapsible message and auto-fed to the agent as context. Same engine as the `recall` tool.
|
|
477
|
-
|
|
478
|
-
```
|
|
479
|
-
/blackhole-recall auth token # active-lineage search, ranked
|
|
480
|
-
/blackhole-recall auth token page:2 # paginated (5 results/page)
|
|
481
|
-
/blackhole-recall hook|inject # regex
|
|
482
|
-
/blackhole-recall fail.*build scope:all # regex across all lineages
|
|
483
|
-
/blackhole-recall mode:file # search only write/edit file content
|
|
484
|
-
/blackhole-recall mode:touched # aggregate view of all files touched
|
|
485
|
-
/blackhole-recall # recent 25 entries
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### Details
|
|
489
|
-
|
|
490
|
-
**File drill-down** reads the raw session JSONL to extract file content from tool call operations. Supports offset/limit paging so you can browse long files. Note: edit diffs are not indexed for text search — drill-down reads them from the raw session as original full-file writes.
|
|
491
|
-
|
|
492
|
-
**Touched mode** (`mode:touched`) aggregates all files written, edited, or read across the session, grouped by path. Each entry shows which tool operation touched the file and the line count. Useful for getting a lay of the land after a long session.
|
|
245
|
+
> **Note:** The OM injection format uses `## Reflections` and `## Observations` Markdown headers followed by a brief footer. Each observation and reflection has a 12-char hex identifier the agent (and you, via `/blackhole-recall`) can use to recover source evidence. When no observations or reflections exist, only the short recall-guidance footer is appended.
|
|
493
246
|
|
|
494
247
|
---
|
|
495
248
|
|
|
@@ -522,26 +275,53 @@ rm -rf ~/.pi/agent/pi-blackhole
|
|
|
522
275
|
|
|
523
276
|
---
|
|
524
277
|
|
|
278
|
+
## Documentation map
|
|
279
|
+
|
|
280
|
+
| Doc | Audience | What's in it |
|
|
281
|
+
|---|---|---|
|
|
282
|
+
| **[`README.md`](README.md)** | You, now | Install, commands, the pitch, the value, the demo. |
|
|
283
|
+
| **[`CHANGELOG.md`](CHANGELOG.md)** | You | Every release, what changed, who contributed. |
|
|
284
|
+
| **[`CONFIG.md`](CONFIG.md)** | You, when tuning | Every config key with type, default, behavior, and env-var overrides. |
|
|
285
|
+
| **[`llms.txt`](llms.txt)** | Your agent | Step-by-step guided setup interview, anti-patterns, exact file paths, internal constants. |
|
|
286
|
+
| **[`MIGRATION-GUIDE.md`](MIGRATION-GUIDE.md)** | You, if upgrading | Old → new config key mapping, semantic changes, automatic migration behavior. |
|
|
287
|
+
| **[`OLD_CONFIG.md`](OLD_CONFIG.md)** | Reference only | The legacy pi-vcc / pi-observational-memory config surface. Kept for historical context. |
|
|
288
|
+
| **[`example-config.json`](example-config.json)** | You | Annotated example config with comments. |
|
|
289
|
+
| **[`docs/APPEND_COMPACTION.md`](docs/APPEND_COMPACTION.md)** | You, if curious | Rules for `compactionSummaryMode: "append"`. |
|
|
290
|
+
|
|
291
|
+
> **Note:** Files under `docs/` are working documentation for contributors and are not published to npm. The README, CHANGELOG, CONFIG, llms, and the two migration files are the public surface.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Migration from an older version
|
|
296
|
+
|
|
297
|
+
If you're upgrading from a pre-0.4.0 config (the old `pi-vcc` / `pi-observational-memory` keys, or an early `pi-blackhole` config with `overrideDefaultCompaction` / `noAutoCompact` / `passive`): see **[`MIGRATION-GUIDE.md`](MIGRATION-GUIDE.md)** for the key mapping, semantic changes, and notes on automatic migration.
|
|
298
|
+
|
|
299
|
+
The short version: old keys are auto-migrated in memory at load time and the on-disk file is never mutated. Set the new keys explicitly via `/blackhole settings` (alias `/blackhole configure`) to silence the migration notification.
|
|
300
|
+
|
|
301
|
+
The legacy config surface is documented at **[`OLD_CONFIG.md`](OLD_CONFIG.md)** for reference only — no new keys are added there.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
525
305
|
## Credits
|
|
526
306
|
|
|
527
|
-
pi-blackhole started as a merge of two upstream projects
|
|
307
|
+
`pi-blackhole` started as a merge of two upstream projects but has since diverged significantly. The codebase still carries DNA from both:
|
|
528
308
|
|
|
529
|
-
- **[pi-vcc](https://github.com/sting8k/pi-vcc)** by @sting8k — algorithmic conversation compaction (the `compile()` pipeline, section extraction, recall core)
|
|
530
|
-
- **[pi-observational-memory](https://github.com/elpapi42/pi-observational-memory)** by @elpapi42 — session-ledger-based observation/reflection capture, memory agents, ledger folding
|
|
309
|
+
- **[pi-vcc](https://github.com/sting8k/pi-vcc)** by @sting8k — algorithmic conversation compaction (the `compile()` pipeline, section extraction, recall core).
|
|
310
|
+
- **[pi-observational-memory](https://github.com/elpapi42/pi-observational-memory)** by @elpapi42 — session-ledger-based observation/reflection capture, memory agents, ledger folding.
|
|
531
311
|
|
|
532
312
|
What blackhole adds and reworks on top:
|
|
533
313
|
|
|
534
|
-
- **Unified configuration** — one JSON file, not two
|
|
535
|
-
- **Per-worker model fallback chains** with persisted cooldowns that survive Pi restarts
|
|
536
|
-
- **Manual flush mode** — `compaction: "manual"` saves observations to per-session disk buffers
|
|
537
|
-
- **Conflict resolution** — OM hooks into vcc's compaction, not Pi's default
|
|
538
|
-
- **Memory toggle** (`/blackhole om-off` / `/blackhole om-on`) — disable the memory layer without uninstalling
|
|
539
|
-
- **Per-session pending state** — isolated per-session JSON files, no cross-session contamination
|
|
540
|
-
- **Custom provider bridge** — consolidation agents loaded via jiti can still use provider stream functions registered by other extensions
|
|
541
|
-
- **Retryable error detection with per-model cooldowns** — models that fail get cooled down, fallbacks tried automatically, 30-second retry gate prevents spam
|
|
542
|
-
- **Improved observer/reflector/dropper prompts** — each heavily customized with detailed extraction rules, relevance guidance, and error handling
|
|
543
|
-
- **OM-recall coupling** — when expanding session entries via `recall`, related observations and reflections are automatically shown
|
|
544
|
-
- **Thinking level support** — per-model `thinking` field for reasoning effort control
|
|
314
|
+
- **Unified configuration** — one JSON file, not two.
|
|
315
|
+
- **Per-worker model fallback chains** with persisted cooldowns that survive Pi restarts.
|
|
316
|
+
- **Manual flush mode** — `compaction: "manual"` saves observations to per-session disk buffers.
|
|
317
|
+
- **Conflict resolution** — OM hooks into vcc's compaction, not Pi's default.
|
|
318
|
+
- **Memory toggle** (`/blackhole om-off` / `/blackhole om-on`) — disable the memory layer without uninstalling.
|
|
319
|
+
- **Per-session pending state** — isolated per-session JSON files, no cross-session contamination.
|
|
320
|
+
- **Custom provider bridge** — consolidation agents loaded via jiti can still use provider stream functions registered by other extensions.
|
|
321
|
+
- **Retryable error detection with per-model cooldowns** — models that fail get cooled down, fallbacks tried automatically, 30-second retry gate prevents spam.
|
|
322
|
+
- **Improved observer/reflector/dropper prompts** — each heavily customized with detailed extraction rules, relevance guidance, and error handling.
|
|
323
|
+
- **OM-recall coupling** — when expanding session entries via `recall`, related observations and reflections are automatically shown.
|
|
324
|
+
- **Thinking level support** — per-model `thinking` field for reasoning effort control.
|
|
545
325
|
|
|
546
326
|
## License
|
|
547
327
|
|