Passer au contenu principal
B

dsh-longterm-memory

bufan528/dsh-longterm-memory

Local Markdown long-term memory for DSH: an Obsidian-compatible vault, a sidebar management page, four memory tools, and budgeted per-turn recall.

Installer

dsh plugin --profile web add github:bufan528/dsh-longterm-memory

README

DSH Memory Vault icon

DSH Memory Vault · 长期记忆

Long-term memory for DeepSeek Harness, stored as a plain Markdown vault you own.

A first-level sidebar page, four model tools, token-budgeted recall, and a durable history journal — no database, no telemetry, no cloud. Your memories stay as Obsidian-compatible .md files on disk.

GitHub stars MIT License DSH 0.2.1-rc.2 Node >= 20 Preview listed on dsh.works available in dshmarket (in-app Plugin Market)

Install · DSH Plugin Market · dsh.works · Features · Configuration · Data safety · Privacy · Development · 简体中文

Project status (2026-10-21). dsh-longterm-memory@0.1.4 is published on npm, attached to the latest GitHub Release, and listed in two community registries: the DSH Plugin Market (added 2026-10-19) and the dsh.works community registry (dshworks/awesome-dsh-plugins, verified, added 2026-10-19). The in-app 插件市场 / Plugin Market is the dshmarket plugin and reads that same catalog, so the plugin is discoverable and one-click installable there as well (no separate submission). Install it from the in-app market, or from npm with dsh plugin add dsh-longterm-memory@latest. The desktop-app plugin entry is verified end-to-end in the running desktop app (61/61 real-browser checks over all five tabs, real vault, restored afterwards). See Install, What's new and Project status & limitations.


What's new

0.1.4 is a documentation release: the plugin is now listed in the DSH Plugin Market (added 2026-10-19) and in the dsh.works community registry (dshworks/awesome-dsh-plugins, verified; it powers the 插件 → DSH 社区 market in the dsh-armory dashboard). Install or update from the in-app 插件市场 / Plugin Market, or from npm. No code changes; it ships all of the 0.1.3 fixes below.

0.1.3 made the Inbox actionable and fixed three other user-facing bugs:

  • Inbox is actionable. 确认入库 / Confirm and 拒绝 / Reject now work for in-memory candidates. Confirming writes an active memory (low confidence is raised to medium), folds a duplicate/supplement into the existing memory instead of duplicating it, and keeps both sides of a contradiction. Rejecting writes no file.
  • Status changes on extracted memories work. A multi-line evidence: block scalar no longer blocks saves with unsafe-edit.
  • The UI language setting works (it previously lost to the host locale).
  • No more permanent "unsaved changes" hint on the settings page.
  • New real-browser E2E suite (npm run verify:e2e) covering all five tabs, including the Inbox, detail, settings, batch and merge flows.

Full details: CHANGELOG.md · latest release

Inbox confirm/reject fixed Merge dialog

Why DSH Memory Vault?

Most "agent memory" features are a vector store or a black-box service. DSH Memory Vault makes the opposite trade-off:

  • Markdown is the only source of truth. Each memory is a human-readable note with YAML frontmatter. Read, edit, link and back it up in Obsidian or any text editor. There is no proprietary format and no export step.
  • The index is disposable. .dsh-memory/index.json is derived data; delete it and the plugin rebuilds it from Markdown. Losing the index never loses a memory.
  • Recall is budgeted and transparent. Injection is computed per assembly from the current index with explicit token/item caps; the page shows exactly what the model would receive.
  • History is durable. Every change is recorded in a journal with before/after digests, reasons and timestamps. A write-ahead outbox keeps history safe across crashes — including the verified window where the Markdown is committed but the journal append has not happened yet.
  • Local by default. No network requests, no model calls, no telemetry; the only traffic is the local RPC between the management page and the DSH host.

Features

First-level sidebar pageRegisters a sidebar.panellist entry and a full management page (overview, search, detail, manage, inbox, settings) — not a chat tab.
Four model toolsmemory_search, memory_get, memory_save, memory_forget (save refuses credential-like content).
Automatic extractionRule-based, fully local candidate extraction at the real turn/end boundary. Optional model-assisted extraction is off by default.
Ranked recallBM25-style lexical ranking over Markdown, with type/status/tag filters and a token budget.
Memory lifecyclepending → active → stale / superseded / archived / conflict, plus low/medium/high confidence. Low confidence and sensitive content wait in the Inbox for human confirmation.
Safe updatesDeterministic dedupe/merge rules: duplicates merge, additions update while keeping sources, contradictions keep both sides, low confidence goes to Inbox.
Conflict handlingConflicting facts are kept side by side, never silently overwritten; a conflict-resolution page supports keep / merge / both.
Crash-safe writesSingle-file atomic replace, per-file lock, optimistic checksum concurrency, durable journal outbox with idempotent recovery.
Obsidian compatibleThe vault carries .obsidian/, [[wikilinks]], stable frontmatter and a human-readable Index/.
Bilingual UIChinese and English (`language: zh
No runtime dependency on @deepseek-ai/*The host half only uses the Cordis context passed in, so DSH internals can change without breaking the bundle.

Interface

Real acceptance screenshots (headless Chrome, real host data — no mocks):

Sidebar entryManagement page
Sidebar entryMemory page

More: overview · search · manage · inbox · settings · dark theme

How it works

flowchart LR
  A[DSH host] -->|tools / prompt section| P[Memory Vault host plugin]
  U[Sidebar page] -->|local HTTP RPC| P
  P --> V[(Markdown vault<br/>source of truth)]
  P --> I[(index.json<br/>derived)]
  P --> J[(journal outbox<br/>history)]
  P --> Q[(quarantine<br/>unreadable notes)]
  V -. rebuild .-> I
  J -. recover .-> V
  • The host owns the vault, index, journal and extraction; it never calls a model unless you explicitly enable model-assisted extraction with your own provider.
  • The management page reads and writes through a loopback-only RPC surface (POST /dsh-longterm-memory/api/<method>, 27 methods) guarded by a browser-trust fence (loopback / trusted hosts, Origin, sec-fetch-site).
  • Recall: memory_search and automatic injection share one engine; explicit recall may include retired memories (labelled history), injection only uses current facts. POST /api/previewStanding and POST /api/previewRecall return the exact text that would be injected.

Install

In the official desktop app, open 插件市场 / Plugin Market, search for 长期记忆 or DSH Memory Vault, then install or update from the plugin card and restart the app when prompted. That in-app market is the dshmarket plugin (dshmarket.com); it reads the same awesome-dsh-plugin catalog (added 2026-10-19), so no separate dshmarket submission or association is needed — the live registry already shows 0.1.4 with the five screenshots. After the first listing, each npm publish makes the new version available for one-click updates.

Market page: https://awesome-dsh-plugin.com/p/bufan528/dsh-longterm-memory/

Also discoverable via dsh-armory. The dsh-armory dashboard's 插件 → DSH 社区 market reads the dshworks/awesome-dsh-plugins registry (browse at dsh.works), where this plugin is listed as verified with npm dsh-longterm-memory. There is no separate submission to dsh-armory: keeping the npm latest tag current keeps both listings current.

Option B — install the latest from npm

dsh plugin --profile web add dsh-longterm-memory@latest

Latest release: dsh-longterm-memory@0.1.4. Use @latest (or omit the version) so an installation always fetches the newest published version.

Option C — download the latest packaged tarball (no build required)

The newest .tgz (and its .sha256) is attached to every GitHub Release:

# Download the latest release asset into the current directory
gh release download --repo bufan528/dsh-longterm-memory --pattern "*.tgz" --dir .
dsh plugin --profile web add .\dsh-longterm-memory-0.1.4.tgz

No gh? Open https://github.com/bufan528/dsh-longterm-memory/releases/latest and download the asset manually.

Option D — build this repository and install the tarball (verified)

Requires Node.js ≥ 20 and a DSH CLI. Use an isolated DSH_HOME so the test profile cannot touch your daily DSH profile:

# 1. Build and pack
npm install
npm run build
npm pack                     # -> dsh-longterm-memory-0.1.4.tgz

# 2. Install into an isolated profile
$env:DSH_HOME = "<temporary dir>"                # PowerShell
# export DSH_HOME="<temporary dir>"              # bash
dsh plugin --profile lmv add .\dsh-longterm-memory-0.1.4.tgz

# 3. Start
dsh --profile lmv --no-open --port 0

Open the Web UI, click 长期记忆 / Long-term Memory in the sidebar, and choose a vault directory (or let the plugin initialize one). You can also pre-set it:

# <DSH_HOME>/profiles/lmv/cordis.patch.yml
- id: longterm-memory
  name: dsh-longterm-memory
  config:
    vaultPath: 'D:/path/to/DSH Memory'
    language: zh

Data-location warning. If vaultPath is unset, the plugin initializes the default location (~/Documents/DSH Memory on Windows). DSH_HOME isolates the profile, not the vault. Always set vaultPath when testing.

Quick start

  1. Install as above and open the page.
  2. Click 初始化 / Initialize and pick a folder (an existing Obsidian vault works).
  3. Create a memory with 新建 / New, or let automatic extraction collect candidates at the end of a turn; low-confidence items appear in 收件箱 / Inbox.
  4. Ask the model something related; the plugin injects the standing section and the tools return ranked hits from the vault.
  5. Open 设置 / Settings to tune budgets, per-step recall, extraction and language.

Vault layout

DSH Memory/
├── README.md                  # generated; user edits are preserved
├── Memory Home.md             # entry page
├── .obsidian/                 # makes Obsidian treat it as a vault
├── Profile/  Preferences/     # profile, long-term preferences
├── Projects/  Projects/State/ # projects and project state
├── Decisions/  Knowledge/     # decisions, knowledge
├── Experiences/  Tasks/       # lessons, tasks
├── Inbox/                     # candidates awaiting confirmation
├── Archive/  Conflicts/       # retired / contradictory memories
├── Index/                     # human-readable index (regenerated)
├── History/                   # change-history notes
└── .dsh-memory/               # config.json, index.json, journal/, quarantine/

Memory types: profile, preference, project, project-state, decision, knowledge, experience, task. Status: active, pending, stale, superseded, conflict, archived. Format details: docs/storage-format.md.

Configuration

All settings are optional; defaults live in src/host/config.ts and can be overridden from your profile's cordis.patch.yml.

KeyDefaultMeaning
vaultPathauto-discover / initializeAbsolute memory vault path
languagezhUI language (zh / en)
enableToolstrueExpose the four model tools
enablePromptSectiontrueInject the standing memory section
standingBudgetTokens700Token cap for the standing section
standingMaxItems12Item cap for the standing section
recallBudgetTokens600Token cap for one recall answer
recallMaxItems8Item cap for one recall answer
enablePerStepRecallfalseSplice retrieved memory into each step (replayed for the rest of the session)
enableAutoExtractiontrueRule-based extraction at turn end (local)
enableLlmExtractionfalseOptional model-assisted extraction (sends turn text to your provider)
redactSecretstrueRefuse credential-like candidates
sensitiveNeedsConfirmationtrueHealth/finance/identity content waits for confirmation
maxCandidatesPerTurn5Extraction cap per turn

Data safety

  • Atomic single-file writes (temp file + rename) and a per-file lock with stale-lock detection; the lock is released on failure, never leaked.
  • Optimistic concurrency: edits carry the expected checksum; a stale edit is rejected with a reload hint instead of overwriting someone else's change.
  • Index is rebuildable: rebuildIndex / syncIndex recover from a deleted or corrupt index. Corruption diagnostics are surfaced, not hidden.
  • Durable journal: every change gets a before/after digest, reason and timestamp. A write-ahead outbox recovers when the monthly archive fails, with idempotent re-archiving and content-conflict detection (same event id + different payload is an explicit integrity error, never a silent merge).
  • Crash-window tests: commit boundaries are exercised with real child-process SIGKILLs, not simulated exceptions — including "Markdown written, commit marker not yet persisted" and "recovery itself interrupted".
  • Quarantine: notes that cannot be parsed safely are isolated, never deleted.

Privacy

  • No telemetry and no outbound network calls by default. Host-side acceptance runs showed zero network calls; the only client request target is the local DSH RPC. The 0.1.3 desktop E2E run exercised the real page and asserted zero page errors / uncaught exceptions; it is not a packet-level network audit.
  • Model use is opt-in: automatic extraction is rule-based and local; model-assisted extraction (enableLlmExtraction) is off and, when enabled, uses the provider you configured in DSH.
  • Secrets are refused: credential-like content (passwords, API keys, tokens, private keys) is blocked before it reaches the vault; sensitive categories require explicit confirmation.
  • Injection is data, not instructions: memories are wrapped and labelled as untrusted data for the model. See docs/privacy.md.

Compatibility

DSH runtime>=0.2.1-rc.2 <0.2.2 (engines.dsh; 0.2.0-rc.2 is not supported)
Verified DSH version0.2.1-rc.2 (host + real headless Chrome acceptance)
Node.js>=20
PlatformWindows (primary), Node path rules elsewhere
npm packagedsh-longterm-memory — 0.1.4 published (latest)
Downloadsnpm @latest, or the tarball on the latest GitHub Release
DSH Plugin MarketListed in awesome-dsh-plugin since 2026-10-19; updates follow the npm latest tag
dshmarket (in-app market)Listed through the same awesome-dsh-plugin catalog; the live registry checks showed 0.1.4 with 5 screenshots on 2026-10-21 (no separate dshmarket submission)
dsh.works registryListed + verified in dshworks/awesome-dsh-plugins since 2026-10-19; surfaced by the 插件 → DSH 社区 market in the dsh-armory dashboard

The dsh.compatibility field is informational; engines.dsh is the only decision source. Details and evidence: docs/compatibility.md.

Development

npm install
npm run build        # tsc -> lib/host, esbuild -> lib/client.js
npm run typecheck    # tsc --noEmit
npm run lint         # contract checks + version-consistency check
npm test             # full suite (currently 41 files / 595 cases)
npm run check        # build -> typecheck -> lint -> test (clean checkout safe)
npm run pack:plugin  # build + npm pack
npm run verify:e2e -- --url "http://127.0.0.1:<port>/?token=..."   # real-browser E2E (61 checks)

verify:e2e drives a real Chrome over CDP, clicks the real management page and checks every effect through the plugin RPC and the Markdown files on disk. For a token-guarded desktop listener, mint the desktop launch cookie for the current machine and pass it with --cookie-file <name=value file>.

Tests cover unit, integration, packaging, real HTTP-route validation, and deterministic fault injection (including real subprocess kills). The browser acceptance scripts are zero-dependency CDP clients using Node's built-in WebSocket.

Project status & limitations

  • Preview: API and storage format may still change; 0.1.0 was the first public version, 0.1.4 is the current release.
  • npm published: dsh-longterm-memory@0.1.4 (2026-10-20); registry installation verified. The npm latest dist-tag and the GitHub Release always point at the newest version.
  • Listed in the DSH Plugin Market: the plugin is in the awesome-dsh-plugin catalog (added 2026-10-19). Install it from the in-app 插件市场 / Plugin Market; future releases are picked up automatically from the npm latest tag, so no new marketplace submission is needed per version. The China-region catalog mirror may lag the origin by up to about a day.
  • Available in dshmarket (in-app Plugin Market): the dshmarket plugin reads the same awesome-dsh-plugin catalog live on every open, so this plugin is already reachable in 插件市场 / Plugin Market — no separate dshmarket submission, claim, or association step exists. The live registry on 2026-10-21 showed version 0.1.4 with 5 screenshots; updates follow the npm latest tag.
  • Also listed in dsh.works: the entry in dshworks/awesome-dsh-plugins is status: verified with npm: dsh-longterm-memory (added 2026-10-19), so the 插件 → DSH 社区 market in the dsh-armory dashboard lists and installs it without any separate dsh-armory submission. Both registries follow the npm latest tag; dsh-armory revalidates its catalog cache every few minutes (new installs fetch fresh).
  • Desktop verified: the full real-browser E2E suite passes against the running desktop app (61/61 checks, all five tabs, real vault restored afterwards).
  • Known follow-ups: in-memory Inbox candidates are drafts — they are not counted in 待确认数量 / the Inbox/ folder until confirmed; they leave the Inbox when confirmed or rejected. A few concurrency and move-atomicity edge cases remain open; frontmatter and lock regressions found in review were fixed in 0.1.0 and are locked by tests.
  • Vault location: with vaultPath unset the plugin initializes ~/Documents/DSH Memory. Set it explicitly to keep test data isolated.

Documentation

DocContents
docs/architecture.mdArchitecture, DSH API usage, prompt assembly
docs/storage-format.mdMarkdown / frontmatter / index / journal formats
docs/privacy.mdPrivacy and threat model
docs/compatibility.mdCompatibility contract and evidence
docs/verification.mdVerification log and acceptance evidence
CHANGELOG.mdRelease notes for every published version
docs/troubleshooting.mdRecovery and FAQ
docs/evidence/Screenshots and raw acceptance data

License

MIT

Plugins associés