feat(plugins): add mempalace-indexer — local semantic memory for agents (#43)
This commit is contained in:
10 files changed
+1305
No files matched your search
@@ -0,0 +1,87 @@
|
||||
# mempalace-indexer
|
||||
|
||||
LibreFang plugin for persistent, local semantic memory via [MemPalace](https://github.com/milla-jovovich/mempalace). No API keys, no cloud.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
librefang plugin install mempalace-indexer
|
||||
librefang plugin requirements mempalace-indexer
|
||||
|
||||
mempalace init /path/to/workspace --yes
|
||||
mempalace mine /path/to/workspace
|
||||
```
|
||||
|
||||
Restart the daemon. Done.
|
||||
|
||||
## Hooks
|
||||
|
||||
| Hook | When | What |
|
||||
|------|------|------|
|
||||
| `ingest` | Message arrives | Searches palace for relevant memories, injects into context |
|
||||
| `after_turn` | After LLM responds | Auto-saves memorable turns with dedup + classification |
|
||||
| `prune` | On demand / scheduled | Deletes drawers older than `MEMPALACE_MAX_AGE_DAYS` |
|
||||
|
||||
## How after_turn saves
|
||||
|
||||
Five filters run before writing to the palace:
|
||||
|
||||
1. **MCP dedup** — skip if the agent already called `mcp_mempalace_add_drawer` this turn
|
||||
2. **Length** — skip exchanges under `MEMPALACE_MIN_CHARS` (default 80)
|
||||
3. **Relevance** — English text must match keywords (decisions, appointments, contacts, etc.); non-English passes on length alone
|
||||
4. **Content dedup** — skip if a near-identical turn was already saved (SHA-256 hash store)
|
||||
5. **Noise** — code blocks are stripped; residual tool/error output is discarded
|
||||
|
||||
Matched turns are classified and written to the appropriate room:
|
||||
|
||||
| Content type | Wing | Room |
|
||||
|---|---|---|
|
||||
| Contacts, email addresses, family | `people` | `contacts` |
|
||||
| Appointments, meetings, reminders | `time` | `calendar` |
|
||||
| Payments, invoices, expenses | `finance` | `transactions` |
|
||||
| Packages, shipments | `logistics` | `orders` |
|
||||
| Decisions, preferences | `knowledge` | `decisions` |
|
||||
| Everything else | `default` | `sessions` |
|
||||
|
||||
A single turn can match multiple rooms and will be written to all of them.
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings are optional environment variables:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `MEMPALACE_PALACE_PATH` | `~/.mempalace/palace` | Palace directory |
|
||||
| `MEMPALACE_MIN_CHARS` | `80` | Minimum text length to save |
|
||||
| `MEMPALACE_WINDOW_SIZE` | `6` | Recent messages to consider |
|
||||
| `MEMPALACE_DEDUP_MAX` | `500` | Hash store rolling cap |
|
||||
| `MEMPALACE_LANG_DETECT` | `1` | Set to `0` to disable language detection |
|
||||
| `MEMPALACE_MAX_CHARS` | `300` | Max characters per injected memory snippet |
|
||||
| `MEMPALACE_MIN_SIMILARITY` | `0.3` | Min similarity score for ingest results (0 = disabled) |
|
||||
| `MEMPALACE_N_RESULTS` | `5` | Number of memories to inject per turn |
|
||||
| `MEMPALACE_MAX_AGE_DAYS` | `90` | Prune drawers older than this (0 = disabled) |
|
||||
|
||||
## MCP server (optional)
|
||||
|
||||
Add 19 explicit memory tools to all agents:
|
||||
|
||||
```toml
|
||||
[[mcp_servers]]
|
||||
name = "mempalace"
|
||||
timeout_secs = 60
|
||||
[mcp_servers.transport]
|
||||
type = "stdio"
|
||||
command = "python3"
|
||||
args = ["-m", "mempalace.mcp_server"]
|
||||
```
|
||||
|
||||
## Pruning
|
||||
|
||||
Run manually:
|
||||
|
||||
```bash
|
||||
python3 ~/.librefang/plugins/mempalace-indexer/hooks/prune.py --dry-run
|
||||
python3 ~/.librefang/plugins/mempalace-indexer/hooks/prune.py
|
||||
```
|
||||
|
||||
Or trigger via the LibreFang hook system on a schedule.
|
||||
Reference in new issue
Block a user