@ztm-njau/dsh-mnemosyne
v0.1.0
Published
Persistent long-term memory for DeepSeek Harness agents: a cross-session `memory` service, a JSON-lines disk provider under $DSH_HOME, and the memory_remember / memory_recall / memory_forget tools.
Maintainers
Readme
@ztm-njau/dsh-mnemosyne
Persistent long-term memory for DeepSeek Harness
agents. Give your agent facts that survive sessions, restarts, and even reinstalls —
stored in one plain, inspectable JSON-lines file under $DSH_HOME.
| Piece | What it is |
|---|---|
| memory service | the cross-session seam your agent (or any plugin) can ctx.get('memory') and call directly |
| disk provider | append-only JSON-lines store at $DSH_HOME/mnemosyne/memory.jsonl |
| memory_remember / memory_recall / memory_forget | the model-facing tools, registered host-side so every session on the profile has them |
Requirements
- DeepSeek Harness (
dsh) installed and working. - pnpm on your PATH —
dsh pluginforwards to pnpm for installs.pnpm --version # if this fails: npm install -g pnpm (or enable corepack: corepack enable)
Install (<2 min)
Add the package to the profile you want memory in (a profile you already boot,
like web or headless):
dsh plugin --profile headless add @ztm-njau/dsh-mnemosyne # or: --profile web, your own profile, …That single command:
- forwards
pnpm add @ztm-njau/dsh-mnemosyneinto the profile, - auto-wires the bundle: because the package declares
dsh.bundle.patch, the profile'sdsh.profile.bundleslist gains@ztm-njau/dsh-mnemosyneautomatically — no manual YAML editing.
A brand-new profile name gets only the base layer (
dsh plugininitializes it with@deepseek-ai/dsh-base, no app) — add your bundle to a profile that already boots.
Verify the rows composed:
dsh --profile <profile-name> --dump-config | grep -A3 @ztm-njau/dsh-mnemosyne
# - id: memory
# name: @ztm-njau/dsh-mnemosyne/memory
# config: { root: ...mnemosyne }
# - id: memory-tools
# name: @ztm-njau/dsh-mnemosyne/toolsThen just boot a session on that profile — the three tools are already there.
Use (the three tools)
memory_remember text="The collaborator prefers a flat white with oat milk." tags=["prefs"]
→ { id: "a1b2…", text: …, createdAt: "…" } # keep the id if you may forget it
memory_recall query="flat white" k=5 tags=["prefs"]
→ { count: 1, entries: [ … ] } # deterministic keyword match, no network
memory_forget id="a1b2…"
→ { ok: true, id: "a1b2…" } # idempotent; unknown ids still succeedmemory_recallmatches by keyword substring + tag score (all requested tags must match), newest first on ties. It is deterministic and local — no embeddings, no network.- Facts persist across sessions and process restarts. Try it: remember a fact in one session, open a second session on the same profile, recall it.
Where the data lives
$DSH_HOME/mnemosyne/memory.jsonl # one JSON object per line, append-only- Crash-friendly: appends only; on load the log is collapsed (last write per
idwins;memory_forgetwrites a tombstone). - Honest guarantees: concurrent writes from two sessions are serialized per process and each append is one short line (atomic for practical purposes), but this is last-write-wins, not ACID. Corrupt lines are skipped and logged — never fatal.
- To wipe memory: delete the file (or
memory_forgetentries one by one).
Use from code (the seam)
Other plugins on the same profile can consume the service directly:
// inside a Cordis plugin's apply(ctx):
const memory = ctx.get('memory') // host plane, one shared store
await memory.remember({ text: '…', tags: ['x'], source: 'my-plugin' })
const hits = await memory.recall({ query: '…', k: 5, tags: ['x'] })
await memory.forget({ id: hits[0].id })
await memory.list({ limit: 10 })Uninstall
dsh plugin --profile <profile-name> remove @ztm-njau/dsh-mnemosyneThis uninstalls the package and drops it from dsh.profile.bundles automatically. The
memory file is left in place ($DSH_HOME/mnemosyne/memory.jsonl) so nothing is lost —
delete it yourself if you want a clean slate.
For preset authors
The two rows are host-plane. Do not copy them into an agent preset: a row that
publishes the memory service collides on the second session mounting it (DSH rejects the
mount with service "memory" has been registered at …). The service belongs in the host
composition — which is exactly what a profile bundle contributes. If you want a preset
whose persona encourages memory use, add the bundle to its profile and mention the tools
in the preset's persona; leave the rows host-side.
Develop / test
node test/provider.test.mjs # 14 provider tests, no DSH runtime neededLicense
MIT
