dsh-memory-graph
Local-first long-term memory and a temporal knowledge graph for DeepSeek Harness.
dsh-memory-graph gives a DSH agent durable, auditable memory without changing DeepSeek Harness itself. It is installed as a regular Cordis plugin, stores data in a private local SQLite database, recalls relevant facts before the first model step, and renders the resulting entity graph inside DSH Web.
Why dsh-memory-graph
- Non-invasive by design. No Harness source patch and no agent-loop fork. Unloading the plugin removes its tools, listeners, route, and UI contributions.
- Memory with history. Stable facts are superseded instead of overwritten, retain provenance, and can be reverted to the previous version.
- A maintainable graph. Canonical names, aliases, entity merge/rename/delete, orphan discovery, reference-aware garbage collection, and normalized predicates keep the graph usable after months of conversations.
- Chinese retrieval that works. FTS5 trigram indexing plus a short-query fallback handles continuous CJK text without relying on whitespace tokenization.
- Hybrid relevance. Recall combines lexical match, graph proximity, importance, time decay, and explicit access reinforcement. Automatic recall is read-only and does not artificially keep old memories alive.
- Inspectable, not opaque. Every automatic memory can retain session, turn, event sequence, model route, extraction request, and extraction response.
- Local-first and fail-open. The database stays on the host. Background summarization failures are logged but never replace or block the original agent response.
Architecture
flowchart LR
T["Conversation turn"] --> S["Background summarizer"]
S --> M["Temporal memory store"]
M <--> G["Canonical entity graph"]
M --> R["Hybrid recall"]
G --> R
R --> A["First agent step"]
M --> V["DSH Web graph"]
G --> V
B["JSONL backup"] <--> M
The plugin uses DSH lifecycle extension points only. Model-visible recalled context is written to the session log, so a recorded session remains reconstructable.
Requirements
- DeepSeek Harness with a configured profile such as
web - Node.js
^22.19.0or>=24.0.0 - Git and npm
Confirm that the CLI and profile are available:
dsh --version
dsh plugin --profile web list
Installation
The project is currently distributed directly from GitHub. Clone it, validate it, then link the local checkout into a DSH profile:
git clone https://github.com/zmh2000829/dsh-memory-graph.git
cd dsh-memory-graph
npm ci
npm run check
dsh plugin --profile web add "$PWD"
dsh web
Open the DSH Web interface and expand Memory graph in the sidebar. The default patch enables automatic recall, automatic turn summarization, and visualization.
Verify the installed link at any time:
dsh plugin --profile web list dsh-memory-graph
Upgrade
The profile points to the local checkout, so an upgrade does not require reinstalling the plugin entry:
cd /path/to/dsh-memory-graph
git pull --ff-only
npm ci
npm run check
Restart the running DSH process after the check completes. Database schema migrations run transactionally when the plugin starts.
Uninstall
dsh plugin --profile web remove dsh-memory-graph
Uninstalling removes the profile link but deliberately preserves the database and JSONL backups. Delete those files separately only when permanent data removal is intended.
Configuration
cordis.patch.yml contains a production-ready local profile. Change the plugin entry in your profile and restart DSH for updates to take effect.
- id: memory-graph
name: dsh-memory-graph
config:
enabled: true
path: !!js dshHomePath('memory-graph.sqlite')
backupDirectory: !!js dshHomePath('memory-graph-backups')
autoRecall: true
autoRecallLimit: 4
autoRecallMinScore: 0.18
autoSummarize: true
summarizeEveryTurns: 1
visualizationEnabled: true
visualizationAutoOpen: true
visualizationRefreshMs: 5000
The major switches are independent:
| Option | Default patch | Purpose |
|---|---|---|
enabled |
true |
Master switch for the entire plugin |
autoRecall |
true |
Recall relevant memory before the first step of each turn |
autoSummarize |
true |
Extract structured memory after successful turns |
visualizationEnabled |
true |
Register the sidebar panel, tool views, and read-only snapshot route |
visualizationAutoOpen |
true |
Expand the sidebar graph when DSH Web starts |
summaryProvider and summaryModel may be configured together to route extraction to a lower-cost or local model. When omitted, summarization uses the current session route. Ranking weights, graph depth, limits, decay, timeouts, and summary thresholds are all configurable in cordis.patch.yml.
For non-loopback Web deployments, add the exact host or host:port values to visualizationTrustedHosts. Remote access is denied by default.
Tools
| Tool | Purpose |
|---|---|
memory_remember |
Atomically write a memory, canonical entities, aliases, and directed relations |
memory_recall |
Run hybrid ranked retrieval with optional graph context |
memory_graph |
Explore a bounded neighborhood or the global graph overview |
memory_forget |
Delete one memory and relations produced by it |
memory_entity_merge |
Merge duplicate nodes and redirect relations |
memory_entity_rename |
Change an entity's canonical display name |
memory_entity_delete |
Remove an entity with explicit reference handling |
memory_entity_orphans |
List graph nodes with no active memory references |
memory_revert |
Restore the previous superseded version of a stable fact |
memory_backup |
Export or restore an exact JSONL database snapshot |
Entity and relation counts returned by write tools represent net-new records. Display names and kinds converge by observed usage and report conflicts instead of silently freezing the first value. Predicates normalize to lowercase snake_case.
Visualization
DSH Web receives an interactive graph with search, drag, zoom, memory details, and periodic refresh. The sidebar reads the store directly through /memory-graph/snapshot; opening the graph never requires a model call.
Visualization failure is isolated from tool rendering. If the dashboard route is unavailable, historical memory_graph tool results still replay normally.
Backup and recovery
Use memory_backup with operation: "export" before migrations, experiments, or manual cleanup. A restore is accepted only when the target database is empty, preventing an import from silently overwriting existing memory.
Backup paths are confined to backupDirectory, and file names cannot contain directory components. The JSONL format captures memories, entities, aliases, relations, provenance, and summary history.
Data and security
- The default database is
$DSH_HOME/memory-graph.sqliteand is created with mode0600. - The store rejects an incompatible schema and databases owned by another application.
- The visualization endpoint is GET-only, returns
Cache-Control: no-store, and validates Host, Origin, and Fetch Metadata. - Recalled memory is explicitly framed as reference data rather than instructions.
- Automatic summarization sends the selected conversation excerpt to the configured model route. Disable
autoSummarizeor use a local route when that data must not leave the host.
Current scope
- Retrieval is lexical and graph-based; the plugin does not run an embedding service or infer arbitrary synonymy. Provide canonical names and aliases, or merge entities explicitly.
- Storage uses synchronous
node:sqliteDatabaseSync. It is appropriate for a personal local memory store, not a multi-host database or a high-concurrency write service. node:sqlitemay emit an experimental API warning on supported Node.js releases.- JSONL restore intentionally requires an empty database.
Development
npm ci
npm run typecheck
npm test
npm run build
npm pack --dry-run
npm run check runs type checking, all unit tests, and the production build. See CONTRIBUTING.md before proposing a change.
License
MIT © dsh-memory-graph contributors.
还没有评论,来写第一条。