dsh-memory ๐Ÿง 

August 16, 2026 ยท View on GitHub

Cross-session memory plugin for DeepSeek Harness (dsh).

YAML-backed remember / recall / view / list / forget / pin tools with embedding search, title-first injection, and two-level (session/auto) automatic injection โ€” the agent "naturally carries" memory without having to remember to call a tool.

English | ไธญๆ–‡

๐ŸŽฏ Injection Strategy: Precise, Conservative, Cache-Friendly

Design PrincipleDescription
Inject once, reuse foreverFixed memories inject on the session's FIRST step only, then ride the history โ€” no per-round re-render
Title-first, expand on demandInjects concise titles (with id); full details expand via view tool โ€” compact prompts
Dynamic memories independent from fixed setauto memories retrieved by topic, never pollute the fixed injection set
Preserves prefix cacheAfter injection, memories enter history; system prompt + history prefix stays identical โ€” LLM KV cache hit rate unaffected
Provenance isolationInjected memories prefixed with Retrieved memories from the memory store (not conversation history) โ€” model never mistakes them for dialogue

๐Ÿ“Š Comparison with Alternatives

ApproachPer-round injectionCache impactToken cost
Full injection every roundโŒ Repeats each roundโŒ Breaks cacheHigh
This pluginโœ… Once at startโœ… Zero impactLow

โœจ Features

FeatureDescription
remember / recall / view / list / forget / pinWrite, semantic search, expand-by-id, list (titles), soft-delete, force-inject pinning
Title-first injectionMemories inject as summary titles (with id), not full text โ€” compact prompts; details expand via the view tool
Two-level injectioninjectLevel: session memories are resident (injected once at session start); auto memories arrive via topic retrieval
Once-per-session injectionFixed memories inject on the session's FIRST step, then ride the history (no per-round re-render โ€” token + prefix-cache friendly)
Embedding searchHybridSearch (keyword 2-gram + local embedding via ollama, RRF fusion) โ€” catches paraphrases keyword search misses
Tuned matchingGeneric-word downweighting (ๆ–‡ไปถ/ๆต‹่ฏ•/ๆ–‡ๆกฃโ€ฆ), โ‰ฅ2-token keyword hits, retrieval gate skips test-chatter ("ๅˆซ็ฎก/ๅชๆ˜ฏๆต‹่ฏ•")
Provenance labelingInjected memories are prefixed "โ€ฆfrom the memory store (not conversation history)" so the model never mistakes them for dialogue
Data safetySerialized write queue (no lost updates), corrupt-file quarantine + backup, atomic writes, mtime cache invalidation

๐Ÿ“ฆ Install

# From source (inside a dsh checkout)
pnpm install
pnpm run build

# Register in your profile patch (e.g. ~/.dsh/profiles/web/cordis.patch.yml)
- insert:
    - id: dsh-memory
      name: '@towzai/dsh-memory'
      config:
        file: /path/to/memory.yaml
        injectLimit: 8

Requires a local ollama instance with an embedding model (default qwen3-embedding:0.6b; override via DSH_MEMORY_EMBED_MODEL).

๐Ÿ”จ Build (from source)

Requires the dsh checkout's dependencies (the plugin's peer deps live there). On Windows you can junction them instead of reinstalling:

# in the plugin repo
cmd /c mklink /J node_modules <path-to-dsh-checkout>\node_modules
npm run build   # outputs lib/index.js

๐Ÿ› ๏ธ Tools

ToolPurpose
rememberSave a memory (content / title / category / tags / importance / forceInject / injectLevel / source)
recallHybrid search (keyword + embedding) top-N
viewExpand ONE memory's full content by id (title-first injection's detail entry)
listList memories as titles (category/tag/importance filters, full for content)
forgetSoft-delete (marks retired, keeps history)
pinToggle forceInject โ€” pinned memories always appear at session start

๐Ÿ—‚๏ธ Storage

Single YAML file (default memory.yaml). Each entry:

- id: MEM-20260814-001
  title: "Summary title (auto-derived if absent)"   # injected as title
  content: "..."
  category: preference | project | lesson | fact
  tags: [tag1, tag2]
  importance: high | normal | low
  created: 2026-08-14
  updated: 2026-08-14
  source: user | agent | conversation
  retired: false
  forceInject: false           # full behavioural rules, always resident
  injectLevel: session | auto  # resident vs on-demand
  vector: [...]   # 1024-dim embedding, auto-computed on write

๐Ÿ”ง Architecture

src/
โ”œโ”€โ”€ index.ts    # plugin entry: tools + session-first injection + pre-step listener
โ”œโ”€โ”€ storage.ts  # Storage interface + YamlStorage (queue, mtime cache, quarantine)
โ”œโ”€โ”€ search.ts   # KeywordSearch / EmbeddingSearch / HybridSearch (RRF) / OllamaEmbedder
โ”œโ”€โ”€ inject.ts   # selectForInjection / renderSection (title-first) / deriveTitle / entryTitle
โ”œโ”€โ”€ dynamic.ts  # DynamicInjector (per-session dedup + retrieval gate + fixed-set exclusion)
โ””โ”€โ”€ types.ts    # data model (+ reserved fields: vector/scope/weight for future)

Architecture: docs/architecture.md ยท Changelog: CHANGELOG.md.

๐Ÿ—บ๏ธ Planned

Ideas on the horizon (not yet implemented):

FeatureDescription
Feedback scoring (weight)Learn from implicit signals (usage, dismissals, agent feedback) and rank memories by usefulness instead of static importance
Multi-scope isolation (scope)Keep separate memory namespaces per project/workspace, so one agent's context never bleeds into another's
Auto-learningDistill session insights into new memories automatically (with human confirmation), instead of relying on explicit remember calls
More backendsSQLite / JSON storage behind the existing Storage interface
Web UIBrowse, edit and manage memories from the dsh WebUI (view only exists as an agent tool today)
Test suiteExpand automated coverage for storage, search and injection logic

โš ๏ธ Notes

  • Embedding model change invalidates stored vectors (dimension mismatch is detected and logged)
  • The plugin is developed against dsh v0.1.0-rc.5; peer dependency ranges may need bumping

๐Ÿ”— References

This plugin is part of the DeepSeek Harness (dsh) plugin ecosystem.

๐Ÿ“„ License

MIT