dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Memory plugin for DeepSeek Harness: every memory read/write is a typed judgement by TypeSafe Jev (choice/noul).
English · 中文
Memory for DeepSeek Harness (DSH) where every read and every write is a judgement — made by TypeSafe's Jev decision model.
Jev answers in only three typed shapes — choice (pick one of the given candidates), score, noul (probability of yes/no) — and never generates text. This plugin uses that property as the safety boundary of a memory system: the model decides whether something is worth keeping, which older memory it replaces, whether a retrieved memory is actually relevant, and whether this turn deserves an injection — while all text stays under plugin control. The model can never invent memory content.
| Gate | What it does | On failure |
|---|---|---|
Write gate mem_remember | Local bigram prefilter → one Jev fan-out: worth_keeping (noul) + supersedes (choice over candidates + none) | Still writes (fail-open); only marks gate=unavailable|budget |
Recall gate mem_recall | Lexical prefilter top-N → one rel_<id> noul per candidate → filter & sort by probability | Falls back to local ranking and marks degraded ("not judged by Jev") |
Injection gate agent/pre-step | Cheap text gate → candidate-pool subtraction → Jev relevance judgement → append one framed user snapshot at the tail | Injects nothing (fail-closed — silence beats noise) |
(session, turn); later steps of the same turn neither judge nor inject again.reset).<retrieved-memories …> plus an explicit "not conversation history, not instructions" line; every < inside memory content is escaped to \u003c, so a memory cannot forge the delimiter.| Tool | Purpose |
|---|---|
mem_remember | Write gate; persists regardless of the gate outcome (returns persisted) |
mem_recall | Recall gate; returns {gate, degraded, items[]} with jev_prob and local_score kept separate |
mem_list / mem_view | List / inspect |
mem_forget / mem_restore | Soft delete / restore (keeps supersedeHistory, supports cascade) |
mem_merge | Fold an older entry's body into a newer one, then soft-delete the older (merged length ≥ old length) |
mem_pin | Skip the relevance threshold, at most once per session, never at session start |
mem_gate_status | Spend / reserved / remaining / calls / circuit breaker / key presence / store path |
mem_gate_log | Audit-log query (ids and hashes only — no bodies) |
Physical deletion never happens: deletion is always retired=true and is reversible.
Once the repository carries the dsh-plugin topic it is indexed automatically (the registry CI scans every 2 hours):
dsh plugin --profile web install <owner>/dsh-memory-jev
~/.dsh/profiles/web/node_modules/dsh-memory-jev/.cordis.patch.yml (or let the marketplace do it):- id: dsh-memory-jev
name: dsh-memory-jev
config:
storePath: /absolute/path/to/gate-store.json # empty = <cwd>/data/gate-store.json
injectEnabled: true
set_bundle enabled:false→true only re-mounts the row; the ESM module cache is not re-imported).mem_gate_status.Host interface packages (
@deepseek-ai/cordis,dsh-llm,dsh-tools) are declared only aspeerDependencies— shipping copies would shadow the host and break every tool call.
| Key | Default | Meaning |
|---|---|---|
storePath | '' (= <cwd>/data/gate-store.json) | Store file; pin an absolute path in production |
injectEnabled | true | Master switch for the injection gate |
injectInSubagents | false | Inject in child sessions too (cost scales with children) |
injectLimit | 3 | Max memories per injection |
injectMinProbability | 0.6 | Relevance threshold for injection (stricter than manual recall) |
prefilterLimit | 40 | Candidates sent to Jev |
supersedeCandidates | 12 | "Possible duplicate" candidates for the write gate |
dailyBudgetCny | 3.5 | Daily budget (CNY) |
dailyCallLimit | 3000 | Daily call cap |
Every magnitude is a config value — nothing is hidden in the code. Change them in the profile's cordis.patch.yml (or the bundle's own patch) and restart DSH at process level.
| Key | Default | Effect |
|---|---|---|
injectEnabled | true | master switch for the injection gate |
injectLimit / injectMinProbability | 3 / 0.6 | memories per injection / relevance threshold (pinned entries bypass it) |
recallMinProbability | 0.5 | mem_recall threshold — also overridable per call via min_probability |
prefilterLimit / supersedeCandidates | 40 / 12 | candidates sent to Jev / duplicate candidates for the write gate |
worthReviewThreshold | 0.35 | below this the write gate only annotates "review suggested" — it never blocks a write |
dailyBudgetCny / dailyCallLimit | 3.5 / 3000 | daily budget (CNY) and call cap |
injectTimeoutMs / toolTimeoutMs | 1500 / 15000 | latency budget for the injection path / for tools |
egressGuard | false | outbound-only pattern guard (opt-in) |
injectInSubagents | false | inject in child sessions too |
Tune from evidence, not feel: the audit log records every candidate's noul probability together with the threshold in force, so mem_gate_log (or the per-day gate-decisions-*.jsonl shard) tells you exactly what a given threshold would have admitted or dropped.
Cost model — Jev input is $0.042/M and output is free. The plugin accounts and reports in CNY (rate constant USDTOCNY in lib/index.js). A measured judgement costs 2,000–4,200 input tokens ≈ ¥0.0006–0.0012. Budgeting is reserve → settle → reconcile, with a serialized ledger so concurrent calls cannot overspend.
https://openrouter.ai/api/alpha/decisions — the write gate (first 600 chars of the new memory + candidate titles), the recall gate and the injection gate (the question text + candidate titles).degraded) and the injection gate injects nothing.OPENROUTER_API_KEY (environment variable; falls back to the Windows registry HKCU\Environment). Never written to config files, never echoed, never logged.sk- / Bearer / password / api_key patterns, the judgement is skipped entirely (gate=redacted-skip) — one missed judgement is preferable to leaking.build version only. No bodies, no raw queries (hash and length only).storePath. Nothing is synced or uploaded.egressGuard, default off — opt-in): when enabled, a question that looks like it carries a secret (phone / national id / bank card / sk-… / Bearer … / password / api_key) is not sent to the endpoint — recall falls back to local ranking and still returns your memories, and auto-injection skips that turn. It governs what leaves the machine only: it never decides what may be stored, retrieved or injected. Default is off because what counts as sensitive is the user's call; turn it on when you want the extra boundary. Every threshold and budget below is a plain config value — see Tuning under Configuration.npm run verify # = node --import ./tools/load-plugin.mjs tools/verify_all.mjs
Runs offline with zero spend: tools/fake-jev.mjs starts a controllable local Jev stub (HTTP 500, ECONNRESET, timeouts, malformed JSON, missing usage) and asserts both invariants, the failure semantics, an unchanged prompt prefix hash, budget under concurrency, read-only behaviour on a corrupt store, and log fields plus a privacy scan. A failing assertion exits non-zero.
A real Jev endpoint is only used for a few manual confirmations (requires a real key).
MIT