Memory

dsh-memory-lite-alanzhao

alanzhao0128/dsh-memory-lite · ★ 2

alanzhao0128

Lightweight zero-dependency memory plugin for DeepSeek Harness: Markdown-file memory store, L0 catalog injection, and 5 model-facing tools.

License
MIT
Added
2026-10-30
Maintenance
active
Install kind
npm
npm
@alanzhao/dsh-memory-lite
Manifest details
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-10-30T09:38:27.374Z
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add '@alanzhao/dsh-memory-lite@0.4.1'

从 npm 安装预构建包

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Quick start (3 steps)
  2. Features
  3. What it costs
  4. Configuration
  5. What the memory looks like
  6. How it works (short version)
  7. Troubleshooting
  8. Uninstall
  9. Known limits
  10. Changelog
  11. v0.4.1
  12. Development
  13. License

English | 简体中文

Cross-session long-term memory for your dsh agent. Plain Markdown files, zero dependencies: preferences, decisions and constraints from a session survive restarts, upgrades and profile switches.

Every dsh session starts from a blank page — transcripts are persisted for audit, but the model never sees them again. This plugin adds that layer back: one resident memory catalog + 5 memory tools + background extraction.

Quick start (3 steps)

# 1. Install (= pnpm add inside the profile; the package is added to
#    dsh.profile.bundles automatically)
dsh plugin --profile web add @alanzhao/dsh-memory-lite

# 2. Restart dsh (the host half and the browser half load at boot)

# 3. Verify — the three checks below

After installing you should see:

  • a memory-lite capsule in the session header: green = last extraction ok, gray = extraction off, red = last extraction failed
  • a full settings page under Settings → memory-lite (screenshot below)
  • ask the model to remember something ("remember that I use pnpm") — it calls remember and a file lands under ~/.agent-memory/peers/<peer>/memories/preferences/ (directories are created on first use)

Compatibility: dsh ≥ 0.1.5 (full support for dsh 0.2.1-rc.2 specification and engines constraint, seamless integration with Working Directory decoupling and managed Subagent Activation isolation; dual-track compatibility for 0.1.7+ SettingsForms/configForms, backward compatible to 0.1.5), Node ≥ 22.

Features

What Notes
Explicit memory (5 tools) read_memory / search_memory / remember / update_memory / forget_memory; update archives the previous content into ## History, forget is a soft delete into .trash/
L0 catalog injection one resident catalog message per session (rendered from _index.md); re-published when the index changes or compaction moves it off the visible surface
Implicit extraction a background run feeds the new conversation window to the model and applies a create / merge / update / skip decision, with dedup search and parse-failure repair
Cross-peer sharing mount another peer's memories read-only under shared/<name>/
Header indicator capsule + three-state dot in the session header, polling the run status every 10 s
Peer isolation the peer name derives from the session cwd (basename + short hash); cwd-less sessions fall back to defaultPeer

What it costs

When Cost
Every step the 5 tool schemas are injected (~300–800 tokens)
Every session one resident catalog message, capped at 1200 tokens by default; near-zero incremental cost once the KV cache hits
Every explicit remember one tool call; the index rebuild costs no LLM
Every implicit extraction one LLM call (two when the answer needs a repair), using your default model or a pinned one

Default triggers: 50 new conversation messages (windowTurns) or 30 minutes idle (idleTimeoutMin); turn-boundary and flush triggers are off by default.

Tip: extraction is a structured JSON task and needs no reasoning. Set reasoning effort = off — otherwise the model can spend the whole output budget thinking (two calls and 20–80 s per run).

Configuration

Everything is edited in Settings → memory-lite and stored under the dsh-memory-lite: section of ~/.dsh/settings.yaml. Most fields apply on save; root and sharing.* need a restart.

Group Field Notes
Extraction Mode incremental (default, implicit extraction on) / explicit_only / off
Triggers Window turns one run once this many new messages accumulate; default 50; 0 = trigger on every message (not a disable)
Idle timeout (min) extract the remaining window after N idle minutes; default 30
Turn-boundary / flush triggers off by default (more expensive)
Min messages / debounce thresholds for the two triggers above
Content Max messages most messages fed to the model per run; default 20
Message scope default user + assistant; raw tool results excluded (cost and noise only); all three unchecked = the default
Tool-result truncation (bytes) only used when "tool results" is checked
Include digest / dedup search both on by default
Model Extraction model follows the live global default model unless pinned to a provider/model
Reasoning effort read from the selected model's declaration; off is recommended
Reliability Parse retry one cheap repair call when the answer is not valid JSON (on by default)
Audit log writes peers/{peer}/sessions/{session-id}.json and extraction.log
Catalog Token cap truncation cap for the L0 catalog, default 1200
UI Indicator order header utilities slot order; refresh the page after saving
Storage Memory root ~/.agent-memory by default, restart to apply
Default peer owner of cwd-less sessions
Cross-peer sharing master switch, restart to apply; individual mounts are picked below

Full schema and defaults: src/config.ts.

What the memory looks like

~/.agent-memory/
├── peers/{peer}/
│   ├── memories/
│   │   ├── _index.md              # L0 catalog (generated; hand-editable)
│   │   ├── preferences/  entities/  events/  experiences/
│   │   │   └── {slug}.md          # L1 full text
│   └── sessions/                  # extraction bookmark + audit + extraction.log
└── .trash/                        # soft-deleted memories (dated folders)

Each memory file uses ## Current / ## History / ## Related; updates archive instead of overwriting. The four categories are retrieval paths for the model: preferences (always relevant), entities (mentioned knowledge), events (time-related), experiences (task lessons).

How it works (short version)

  • Catalog injection: in the agent/pre-step waterfall the peer's _index.md is rendered into one user/message carrying the official plugin source kind with the catalog form; subagent sessions get none.
  • Extraction: triggered by windowTurns or idle → select the window → grep existing memories for dedup → one LLM decision → write files → advance the per-session bookmark. A failed run keeps the bookmark, so the same window is retried on the next trigger.
  • Safety: every file access goes through a containment boundary (relative paths only; .., absolute paths and symlink escapes are rejected at the executor).
  • Concurrency: all writes go through a serial queue with atomic tmp+rename replacement.

Details (design tradeoffs, incident notes, known deviations) live in IMPLEMENTATION.md.

Troubleshooting

Symptom What to do
Nothing happens after installing; the model has no memory tools Restart dsh; check that dsh plugin --profile web ls lists the package and that it is in dsh.profile.bundles
No memory-lite capsule in the header Refresh the page; the slot lives in the header utilities row (order is configurable)
The capsule is red The last extraction failed: read the note of the last line in ~/.agent-memory/peers/<peer>/sessions/extraction.log
Extraction never fires Check, in order: extraction mode, window turns, message scope, max messages (0 = nothing is extracted)
The log says no configured model, or the panel shows 已失效 (stale) The extraction model was renamed or removed — pick another one
Extraction is slow / always parse-error-recovered Reasoning effort is eating the output budget: set it to off
Memories land under the wrong peer The peer derives from the session cwd; cwd-less sessions use defaultPeer (configurable)

Uninstall

dsh plugin --profile web remove @alanzhao/dsh-memory-lite
# restart dsh

Your memories are not deleted: ~/.agent-memory is left for you to keep or remove.

Known limits

  • forget_memory has no approval gate (the model can soft-delete directly).
  • ## Related auto-maintenance is not implemented.
  • No CLI / MCP entry point.
  • The browser half (indicator + settings page) needs the web profile's connection service; under a headless profile the plugin still loads (tools + extraction work) and simply has no browser surfaces.
  • Extraction quality depends on the model you pick; small models produce JSON that needs repair more often.

Changelog

v0.4.1

  • DSH 0.2.1-rc.2 Specification & Engines Alignment: Declared "engines": { "dsh": ">=0.1.2-rc.1" } in package.json, adhering to the official priority evaluation of engines.dsh.
  • Fixed Volatile Reference Validation Bug: Resolved ValidationError during installSettingsCompat by cleanly unwrapping volatile references with unwrapConfig.
  • L0 Catalog Category Priority & Anti-Truncation: Enforced stable output priority in renderIndex (preferences -> entities -> experiences -> events) and expanded default index.maxTokens to 2000, preventing core rules and assets from being dropped by token budgets.
  • Triple Gate for Background Extraction: Overhauled extractionSystem with a strict negative exclusion list, 30-day durability test, and aggressive merge requirement to eliminate over-extraction and memory fragmentation.

Development

npm install
npm run build     # tsc -> lib/
npm test          # node:test + tsx, including a real Loader boot smoke test

License

MIT