Pular para o conteúdo principal
O

dsh-experience-recall

overdustd7/dsh-experience-recall

Cross-project experience recall for DeepSeek Harness: when the running work matches something your memory store already learned elsewhere, that lesson is injected before the next step. Runs fully locally, judged by a local small model.

Instalar

dsh plugin --profile web add github:overdustd7/dsh-experience-recall

README

dsh-experience-recall

中文 | DeepSeek Harness plugin (profile bundle)

npm ci License: MIT node

Your agent forgets what it learned in other projects. This plugin hands it back at the right moment.

It watches what the model is doing — its reasoning, its tool calls, its failures — and when the running work matches something your memory store already learned somewhere else, it injects that one lesson as a short message right before the next step. Everything runs locally: the keyword table, the retrieval and the relevance judge use your own machine by default. Injected messages still consume the host model's context and input tokens.

What it looks like

A real injection from a DSH session (trimmed):

【可能相关的历史经验 · 来自其他项目】
· 验证自研 DSH 宿主插件的一次性宿主法(不必重启 GUI、不碰 ~/.dsh):把 DSH_HOME 指到 %TEMP% 里的临时 home,
  拷入 settings.yaml 与 .credentials.yaml,profile 的 dsh.profile.bundles 只写 [dsh-base, dsh-headless, 自研插件],
  然后用 dsh --profile …(记忆 id: 0f5eddca)

需要细节:用 mnemon_recall / document_search 取全文。

The card is deliberately one line with the reusable conclusion, plus an id so the model can pull the full memory if it needs it. At most a few of these per turn, ~1.2 KB each.

How it works

session/event (reasoning · text · tool arguments · tool results · errors)
  → mechanical keyword match against a vocabulary derived from your memories   (free, no model)
  → gates: once per term per turn · once per memory · cooldown · per-turn quota
  → local small model judges "does this lesson change what I should do next?"  (serialized, ~0.4 s)
  → the ready result is appended at the next agent/pre-step boundary

The boundary never waits: if retrieval or judging is not finished when the next step starts, that step simply proceeds and the card arrives a step later. Nothing is injected on a guess — an unparsable or uncertain judgement is dropped rather than shown.

The vocabulary is not hand-written. It is derived from your memory store (author tags/entities plus the proper nouns in the text) and from your project documents, including each document's ## sections, then filtered for terms that cannot discriminate anything. New memories are picked up automatically after a mnemon_* tool call.

Requirements

NeedWhyWithout it
DSH >= 0.1.5-rc.1host
Node >= 22.5, 24.x recommendednode:sqlite reads the memory store. On Node 22 that module needs --experimental-sqlite; it is unflagged from Node 23.4the plugin still runs, but the memory-derived vocabulary is empty (documents and seed terms keep working)
dsh-mnemon + the mnemon CLImemory indexing and semantic searchwithout the CLI, already indexed cards can still trigger; CLI search is unavailable
A local model on Ollama (http://localhost:11434, default qwen3.5:9b)builds the cards and judges relevanceit observes and logs, but injects nothing — it refuses to guess

Install

dsh plugin --profile web add dsh-experience-recall

web is the profile behind the DSH web UI — substitute your own profile name if you renamed it. The command forwards to your package manager, so it also accepts a repository or a local checkout:

# track this repository instead of the npm release
dsh plugin --profile web add github:OverDustD7/dsh-experience-recall

# development: install the checkout you are working in
dsh plugin --profile web add link:/path/to/dsh-experience-recall

Then restart dsh web. Installing already adds the package to the profile's dsh.profile.bundles — do not add it by hand as well, or the loader fails with duplicate loader entry id.

Verify it works

  • In chat: /experience-recall prints the vocabulary size, scan/hit counters, how many candidates the judge accepted, rejected or never answered (with average latency and retry count), injections, and the last card that got through.
  • On disk: $DSH_HOME/dsh-experience-recall/logs/observe.ndjson records trigger / recall (with the judge's reason) / verify / inject / term-cooldown — "why did it inject / why didn't it" is always answerable. Verdict records also carry which half of the vocabulary fired (source/termKind) and how common that term is.
  • Install self-check: node node_modules/dsh-experience-recall/tools/check-install.mjs (add --cache / --log if you moved the state directory).

Give it a few minutes of real work first: on a fresh install the first start builds one card per memory with the local model (a few hundred memories ≈ 5 minutes), and the vocabulary is thin until that finishes.

Configuration

Everything is optional and lives in the row's config — either in the package's cordis.patch.yml or, better, in your own profile patch ($DSH_HOME/profiles/<name>/cordis.patch.yml), which wins:

- id: experience-recall
  config:
    # state directory (default $DSH_HOME/dsh-experience-recall)
    # stateDir: '~/dsh-experience-recall'
    # keep observing but disable all injections:
    # maxInjectionsPerTurn: 0
    # disable CLI retrieval only (indexed cards can still trigger):
    # mnemonCliPath: ''
    # localModel: 'qwen3.5:9b'
    # minScore: 0.35              # a floor against garbage, not a discriminator
    # verifyEnabled: false        # inject without judging (not recommended)
KeyDefaultMeaning
enabledtruemaster switch
stateDir$DSH_HOME/dsh-experience-recallwhere the log and the card cache live
logPath / cardCachePathunder stateDiroverride individually; cardCachePath: '' disables the cache
mnemonCliPath$MNEMON_CLI_PATHthe mnemon CLI; '' disables CLI retrieval only
mnemonDataDir / mnemonStore$MNEMON_DATA_DIR or $DSH_HOME/mnemon / $MNEMON_STORE or defaultshared by the index reader and the CLI; unset DSH_HOME uses ~/.dsh
localModel / localEndpointqwen3.5:9b / http://localhost:11434card builder + relevance judge
cardBuilderlocalmechanical skips the model when building cards
minScore0.35retrieval score floor
maxInjectionsPerTurn / maxCardsPerInjection / maxInjectBytes3 / 2 / 1200injection budget
verifyEnabled / verifyTimeoutMs / verifyMinIntervalMstrue / 6000 / 1200the relevance gate
verifyRetryTimeoutMs / verifyRetryLimit30000 / 1one retry with a longer budget when the local model never answered — aborting a cold load cancels it in Ollama, so retrying inside the same budget livelocks that load
verifyBackoffBaseMs / verifyBackoffMaxMs2000 / 30000after an unanswered judgement the next start is spaced out (base * 2^n, capped) instead of burning one call per candidate
warmupAttempts / warmupRetryDelayMs3 / 5000how long startup keeps trying to load the local model before real judgements begin
documentFragments / fragmentCharstrue / 200index each document's ## sections as their own cards
systemPromptNotetrueregister the constant explanation section in the system prompt
reinjectTokenDistance / repeatToolLimit / repeatWindowSteps20000 / 3 / 12long-session criteria: forgotten injections, going in circles
termRejectLimit / termBlockCooldownMs3 / 1800000term reputation: a term rejected this often without ever passing is cooled down

What it writes, and what it costs

  • State only, under stateDir: logs/observe.ndjson (rotated at 32 MB) and cache/cards.json. Nothing is written inside node_modules, and no file of yours is modified.
  • Retrieval and judging use the configured endpoints (localhost by default), with no telemetry. A custom endpoint receives the context/card or embedding query needed for its request. Logs contain keyword context and injected card text. The relevance judge runs as a local node subprocess.
  • Context cost is bounded: at most maxInjectionsPerTurn injection blocks per turn, each ≤ maxInjectBytes, with at most maxCardsPerInjection cards per block. Injected text counts toward host model input tokens.

Uninstall

dsh plugin --profile web remove dsh-experience-recall

Then restart. Delete $DSH_HOME/dsh-experience-recall/ if you also want the log and cache gone.

Troubleshooting

SymptomLikely cause
Injections never happencheck the store paths, injection quota, model and endpoint; an unavailable judge drops candidates instead of guessing. Built-in seed terms do not require the model
The log shows many rejected verdicts and few injectthe judge rejects weak or uncertain matches. /experience-recall and term-cooldown show term reputation; unanswered judgements do not count against a term
Nothing is injected for the first minutes after a restartthe local model is loading. Since 0.6.2 a timed-out judgement retries with a longer budget instead of cancelling that load
First start is slowthe card cache is being built: one local model call per memory. Prebuild it with node node_modules/dsh-experience-recall/tools/build-cards.mjs --cache <stateDir>/cache/cards.json
Nothing at all after installthe plugin needs a restart; check ready in the log and that command-registered / system-prompt-section / token-meter appear

Development

Layout:

PathWhat is in it
lib/index.jswiring: per-agent subscriptions to session/event and agent/pre-step, the /experience-recall command, the constant system-prompt section, the token meter
lib/observer.js · lib/scan.jsturn session events into scannable text segments
lib/keywords.js · lib/table.js · lib/terms.jsthe vocabulary: matching, the live term table, term extraction and shape gates
lib/cards.jsbuilds cards (local model + mechanical fallback + document fragments) and owns the disk cache
lib/mnemon-store.js · lib/memory-watch.jsread the memory store (read-only node:sqlite) and reconcile it incrementally
lib/recall.jsthe mnemon CLI search (hard timeout, cache, silent degradation)
lib/verify.js · tools/check-relevance.mjsthe second-stage relevance judge (serialized, retried, backed off)
lib/controller.js · lib/render.js · lib/surface.jsgates, queue, injection boundary; rendering; visibility checks
tools/CLI tools: check-install, build-cards, term-audit, verdict-report, judge-probe, verify-package, and the local evaluation harness
test/124 tests on node's built-in runner

Commands (no install step is needed — the plugin has no dependencies):

npm run check                            # syntax check every runtime module
npm test                                 # 124 unit tests, no network
node tools/check-install.mjs             # installation self-check
node tools/verify-package.mjs            # simulate the published package from `files`
node tools/verdict-report.mjs            # runtime data: sources, scores, judge health
node tools/judge-probe.mjs --n 3         # probe the judge against the real endpoint

lib/config.js holds PLUGIN_VERSION, which mirrors package.json; prepack runs the syntax check and the test suite, so a broken package cannot be published. CI runs the same two commands on Ubuntu and Windows with Node 24.

The labelled pairs used to calibrate the judge prompt are not in this repository: they are drawn from the author's private memory excerpts, so tools/judge-ab.mjs, tools/calibrate.mjs and tools/relevance-lab.mjs only exist in the author's checkout. Everything needed to run, test and package the plugin is here.

  • DeepSeek Harness — the host this plugin runs in
  • dsh-mnemon — the memory store and mnemon CLI it reads
  • awesome-dsh-plugin — the curated list behind the DSH marketplace; GitHub topic dsh-plugin

License

MIT

Plugins relacionados