dsh-plugin-sodamem

memoryinstall failsnpmApache-2.0

Bi-temporal memory backed by a SodaMem daemon: recall is contributed to the prompt while each turn is assembled and every closed turn is ingested, with no tool call and no model call on the read path; each recalled fact cites the turn it came from and carries validity dates, so superseded facts stop

下载量 / Downloads
727
测试时间 / Tested
2026-11-07
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-plugin-sodamem

Sandbox test results

StageResult
1 install✗
2 list—
3 mount—
4 boot—
First error
dsh: initialized profile web at /home/node/.dsh/profiles/web

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-plugin-sodamem

Long-term memory for DeepSeek Harness, backed by SodaMem.

  • Recall — while a turn is being assembled, the plugin retrieves an evidence block for that turn's question and contributes it to the prompt. BM25 + vector + entity fusion, no model call.
  • Retain — when the turn closes, its messages are ingested back into the store.

Neither is a tool call, so the model can't skip either one and neither costs tool-schema space.

SodaMem is a separate open-source memory engine that runs as a local daemon. This repo is only the dsh plugin; you need the daemon running for it to do anything.

What you get that a notes file doesn't

Every recalled fact names the turn it came from. This is one line of a real evidence block, verbatim:

support=I flew United to Boston last week.
predicate=User flew United to Boston
entities=airline=United|destination=Boston
source=s4/s4_turn_0        ← the actual turn, not "some earlier chat"
date=2023-06-10

FactEvent → SourceSpan → RawTurn is a foreign-key chain. When the model asserts something about the user, there is a row explaining why.

Facts expire. SodaMem keeps four time axes — when the event happened, when the fact was true, when it was said, when it was stored. "I moved to Chicago last year" and "I'm moving next year" are different rows, and a fact that stopped being true stops coming back. Corrections are ADD-only: a new version plus a SUPERSEDES edge, never an in-place rewrite.

The engine is benchmarked and the answers are published.

benchmark · score ·

LongMemEval-S · 92.8% (464/500) · 500 answers + 8,427 evidence rows, re-gradable with any judge

LoCoMo · 86.88% (1338/1540) · end-to-end QA, LLM-as-judge

Those are SodaMem's numbers — the engine this plugin talks to, not the plugin itself.

Why not the MCP bridge?

SodaMem already has an MCP integration for dsh, in the main SodaMem repo (integrations/deepseek-harness/). It exposes memory as tools, which means the model has to choose to call them — and on most turns it simply doesn't. The strongest thing SodaMem offers, the zero-LLM GET /v1/context evidence block, ends up left to the model's discretion.

MCP cannot fix that. A tool is pull-only, and nothing in the protocol lets a server contribute to the prompt or observe a turn closing. This plugin uses the harness's own seams instead — system-prompt/assemble for recall and agent/turn-stopping for retain — so both happen unconditionally.

· MCP bridge · This plugin

Recall · model calls a tool, if it decides to · every turn, automatically

Retain · model calls a tool, if it decides to · every closed turn, automatically

Model can skip it · yes · no

Costs tool-schema space · yes · no

Do not run both against the same store. They would recall the same facts twice and ingest every turn twice. Pick one.

Requirements

  • Node >= 22 (the harness requires it; the plugin uses AbortSignal.any)
  • A running SodaMem daemon — see below

Install

dsh plugin --profile tui add dsh-plugin-sodamem

That is all that is needed. The package ships a dsh.bundle manifest pointing

at [cordis.patch.yml](./cordis.patch.yml), so dsh adds the plugin to the

profile's bundle list and composes its row — with working defaults — into the

profile tree. Confirm it landed:

dsh --profile tui --dump-config | grep -A6 'id: sodamem'

Start the daemon first (once per machine):

sodamem daemon ensure          # defaults to http://127.0.0.1:8000

Fact extraction needs LLM credentials on the daemon side. Put SODAMEM_LLM_PROVIDER / SODAMEM_LLM_API_KEY / SODAMEM_LLM_MODEL in the daemon's environment or .env. Without them recall still works, but every retain will be accepted and then fail during extraction.

Configure

The bundled cordis.patch.yml ships defaults that boot (apiUrl

http://127.0.0.1:8000, userId default). To change them, override the row

in your own profile cordis.patch.yml, which applies after every bundle

layer:

# $DSH_HOME/profiles/<profile>/cordis.patch.yml
- id: sodamem
  config:
    apiUrl: 'http://127.0.0.1:8000'
    apiKey: 'dev'
    userId: 'your-user-id'
    tokenBudget: 1200

A patch replaces the targeted row's whole config rather than merging into

it, so restate every key you want to keep.

Without installing as a bundle, the same row can be inserted ad hoc:

npx @deepseek-ai/dsh web --patch ./sodamem-plugin.patch.yml

Config fields

There are four, and they are all connection or scope facts.

field · required · default · what it is

apiUrl · yes · — · Origin of the SodaMem daemon

apiKey · yes · — · Sent on every request. Any non-empty string works when the daemon runs with auth disabled — there is no magic fallback

userId · yes · — · The SodaMem user_id every read and write is scoped to

tokenBudget · no · 1200 · Token budget for the recalled evidence block

There is deliberately no switch that turns recall or retain on or off, and no strategy selector. Auto-injection is the entire point of the plugin; a knob to disable it would just be a slower way to use the MCP bridge.

session_id on retain is the agent's id (in dsh, an agent and its session share one identity). agent_id is deliberately not sent — it would be the session id, which would narrow retrieval and fragment recall across sessions.

Remote mode only

The plugin talks HTTP to a daemon. It has no data-root option and imports nothing that can open a store locally, and that is a deliberate constraint rather than an unfinished feature.

Two processes writing one `SOD

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::2,最后更新 2026-08-18

Links

GitHub · Homepage · npm

Same category