dsh-openviking-memory
Verified@yadsh/dsh-openviking-memory Β· v0.1.0 Β· Apache-2.0
OpenViking memory integration for DeepSeek Harness with configurable automatic context injection; derived from the official OpenViking DSH plugin.
Install
dsh plugin add @yadsh/dsh-openviking-memory Confirm the layer applied with dsh --profile default --dump-config β see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Readme
@yadsh/dsh-openviking-memory
OpenViking memory for DeepSeek Harness: durable memory tools, skills, conversation capture and commit β with automatic profile/recall injection you can switch off entirely.
This package is a community-maintained derivative of OpenViking's official
@openviking/dsh-memory-plugin. It is not maintained or endorsed by the OpenViking project.
Original upstream: https://github.com/volcengine/OpenViking/tree/main/examples/dsh-memory-plugin. Provenance is recorded in UPSTREAM.md.
What it is
A DSH bundle that connects one agent to an OpenViking server and keeps five capabilities independent of each other:
| Capability | What it does |
|---|---|
| Tools | Mounts DSH's MCP bridge against the OpenViking stdio proxy, publishing mcp__openviking__* |
| Skills | Serves the openviking-memory skill so the model knows how to search, read and write memory |
| Capture / commit | Mirrors conversation turns into an OpenViking session and commits it once it grows past a token threshold |
viking:// guard |
Denies any filesystem or shell tool call that is handed an OpenViking URI, with a hint naming the right tool |
| Automatic context presentation | Injects the stored profile at session start and/or before each step, and runs semantic recall per step |
The first four are always on. The fifth is what this fork adds control over.
Why this fork exists
Upstream always injects: every session gets the stored profile, and every step gets a recall round-trip. That is the right default, and it stays the default here. It is the wrong behaviour when you want the model to decide when memory is worth the latency and the tokens:
Now I need memory β call the OpenViking search/read tools.
autoInject: false gives exactly that. It is not "memory disabled": tools,
skills, capture, commit and the URI guard all keep working, so the agent still
learns from the conversation and can still recall on demand. Only the automatic
context presentation branch is switched off β and with it, every profile and
recall HTTP request (not "the request is made and the result dropped").
Differences from upstream
autoInjectplus three granular knobs βinjectStartupProfile,injectStepProfile,autoRecall. See the behaviour matrix below.- Zero-work when disabled. With
autoInject: falsethe plugin never calls into the profile or recall machinery, so no profile or recall request is issued at all. - Typed, validated configuration. A Schemastery schema declares ranges and enums, and DSH refuses to load the plugin when a value is out of range instead of silently clamping it. Out-of-range defaults still resolve to the upstream behaviour.
- Repository-conventional package layout. The upstream
.mjssources are ported to TypeScript undersrc/, with a Cordis service, a@yadshstructured log file under<$DSH_HOME>/logs/dsh-openviking-memory/, and the monorepo's build/release tooling. - No bundler group wrapper. Upstream's bundle patch nested the runtime in a
@deepseek-ai/cordis-plugin-grouprow withisolate: { openvikingMemory: true }. This fork uses the canonical single-row patch and provides the service from a CordisServicesubclass instead. See docs/upstream-sync.md for what that means when syncing upstream changes. - Dropped upstream code that no DSH caller used (cross-harness session bypass helpers, rollout-log ingestion, the doctor surface). The complete list is in SPEC.md.
Do not run both plugins at once
Remove or disable the official @openviking/dsh-memory-plugin before enabling
this package. Running both in one profile means duplicate capture, duplicate
recall, duplicate MCP registrations, conflicting services and duplicate skill
providers.
Install
dsh plugin --profile <profile> add @yadsh/dsh-openviking-memory
--profile is required. From a checkout instead:
pnpm nx run @yadsh/dsh-openviking-memory:build
dsh plugin --profile <profile> add ./plugins/dsh-openviking-memory
Quick start
Point the plugin at your OpenViking server and keep the upstream defaults:
- insert:
- id: dsh-openviking-memory
name: "@yadsh/dsh-openviking-memory"
config:
endpoint: http://openviking:1933
Credentials are resolved in upstream's order: explicit config β OPENVIKING_URL
/ OPENVIKING_API_KEY / OPENVIKING_ACCOUNT / OPENVIKING_USER /
OPENVIKING_PEER_ID β ~/.openviking/ovcli.conf β ~/.openviking/ov.conf.
Manual-only mode
Let the model ask for memory instead of injecting it every step:
- insert:
- id: dsh-openviking-memory
name: "@yadsh/dsh-openviking-memory"
config:
endpoint: http://openviking:1933
# No automatic profile or recall injection.
autoInject: false
# Keep learning from the conversation.
syncTurns: true
captureAssistantTurns: true
captureToolResults: false
Manual-only (autoInject: false) |
|
|---|---|
| Automatic startup profile | off |
| Automatic per-step profile | off |
| Automatic semantic recall | off |
| Conversation capture | on |
| Memory commit | on |
| OpenViking MCP tools | on |
| Skills | on |
viking:// guard |
on |
| Model-initiated recall | on |
Upstream-compatible mode β the default, and what you get by not writing any of these keys:
config:
autoInject: true
injectStartupProfile: true
injectStepProfile: true
autoRecall: true
Behaviour matrix
| Configuration | Startup profile | Per-step profile | Automatic recall |
|---|---|---|---|
| defaults | yes | yes | yes |
autoInject: false |
no | no | no |
injectStartupProfile: false |
no | yes | yes |
injectStepProfile: false |
yes | no | yes |
autoRecall: false |
yes | yes | no |
all three granular false |
no | no | no |
Each granular knob is gated by autoInject, so it can narrow the master switch
but never widen it. When a capability is off, the plugin issues no request on
its behalf.
Configuration
Every key is optional; the default column is what resolveConfig uses when the
key is absent, and it matches upstream.
Injection
| Option | Type | Default | Description |
|---|---|---|---|
autoInject |
boolean | true |
Master switch for automatic context presentation |
injectStartupProfile |
boolean | true |
Inject the stored profile once at session start |
injectStepProfile |
boolean | true |
Inject the profile before a step while undelivered |
autoRecall |
boolean | true |
Run automatic semantic recall before each step |
Connection
| Option | Type | Default | Description |
|---|---|---|---|
endpoint |
string | (from credentials, else http://127.0.0.1:1933) |
OpenViking base URL |
apiKey |
string | "" |
Bearer token |
account |
string | "" |
X-OpenViking-Account header |
user |
string | "" |
X-OpenViking-User header |
peerId |
string | "" |
Explicit actor peer id; skips workspace derivation |
workspacePeer |
boolean | true |
Derive a peer id from the workspace |
peerSource |
string | "git" chain |
Peer preset (git, cwd, none) or a template such as team-{dir} |
Recall and profile
| Option | Type | Default | Description |
|---|---|---|---|
recallPeerScope |
"all" | "actor" |
"all" |
Search every peer of the user, or only the caller's |
recallQueryExpansion |
"auto" | "off" |
"auto" |
Server-side query expansion (sent only when you name it) |
recallTokenBudget |
integer 200β50000 | 2000 |
Token budget for one recall block |
recallMaxContentChars |
integer 100β5000 | 500 |
Per-entry character cap |
recallPreferAbstract |
boolean | true |
Use the stored abstract instead of reading the body |
recallLimit |
integer 1β50 | 10 |
Maximum entries per step (naming it switches the server to the client's quota table) |
scoreThreshold |
number 0β1 | 0.35 |
Minimum relevance score |
minQueryLength |
integer 1β64 | 3 |
Shortest prompt that triggers a recall |
profileTokenBudget |
integer 500β50000 | 10000 |
Token budget for the profile block |
recallRewrite |
"off" | "auto" | "client" | "server" |
"off" |
Who builds the digest |
recallDedupTurns |
integer 0β1000 | 5 |
Turns the server de-duplicates against (0 disables) |
recallContextTimeoutMs |
integer 0β600000 | 0 |
Hard deadline for one context request (0 derives it) |
recallMaxTokens |
integer 64β1000000 | 1600 |
Token ceiling for a server-assembled block |
recallCompressMaxBullets |
integer 1β50 | 6 |
Bullet cap when a digest is produced |
Capture and commit
| Option | Type | Default | Description |
|---|---|---|---|
syncTurns |
boolean | true |
Capture conversation turns into the OpenViking session |
captureToolResults |
boolean | false |
Capture tool results as well |
captureMode |
"semantic" | "keyword" |
"semantic" |
Accepted for compatibility; not consumed by this plugin |
captureMaxLength |
integer 200β100000 | 24000 |
Character cap per captured turn |
captureToolMaxChars |
integer 200β1000000 | 1000000 |
Character cap per captured tool payload |
captureAssistantTurns |
boolean | true |
Capture assistant turns as well as user turns |
captureFilters |
string[] | [] |
Sed-style filters: s/pat/rep/, d|pat| (drop), k|pat| (keep only), optionally prefixed user: / assistant: |
skipSubagentSessions |
boolean | false |
Leave delegated subagent sessions entirely alone |
commitTokenThreshold |
integer 1000β1000000 | 20000 |
Commit once the session's pending tokens reach this |
commitKeepRecentCount |
integer 0β1000 | 10 |
Recent turns a commit keeps unsummarized |
Transport
| Option | Type | Default | Description |
|---|---|---|---|
requestTimeoutMs |
integer 1000β120000 | 10000 |
Timeout for one OpenViking request |
mcpToolCallTimeoutMs |
integer 1000β600000 | 60000 |
Timeout for one bridged MCP tool call |
Out-of-range or unknown enum values are rejected by DSH with a validation error
rather than silently coerced. Values supplied through OPENVIKING_* environment
variables keep upstream's clamping behaviour, because they bypass the schema.
OpenViking setup
The plugin talks to a running OpenViking server over HTTP and starts the
bundled stdio MCP proxy as a child process (process.execPath, so it works
inside DSH Desktop where Electron is the executable). Nothing else needs
installing: the MCP bridge itself ships with DSH.
Where memories are filed is OpenViking's decision, not this plugin's. A git
repository derives its peer from origin, so every clone and worktree of one
repository shares one memory; a directory that is neither a repository nor
marked gets no peer of its own. Upstream's ~/.openviking/ovcli.conf is the
usual place to pin actor_peer_id if you want a fixed identity.
Security and privacy
- Credentials never enter agent messages or the log file. API keys and
bearer tokens are only ever sent as request headers; the plugin log records
booleans (
hasApiKey) and never the values. - Capture is a write path, not a read grant.
syncTurnsand its companions control what this plugin sends to your OpenViking; they never widen what a tool call may do. viking://is still guarded. The guard is registered in every mode, includingautoInject: false, and denies filesystem or shell calls handed an OpenViking URI.viking_forgetand the other destructive tools are unchanged. This fork does not add, weaken or auto-approve any tool contract.autoInject: falseis not "memory disabled" β it turns off automatic context presentation only. Treat a profile you no longer want injected as something to remove in OpenViking, not something this knob hides.- The offline pending queue writes raw conversation payloads to
~/.openviking/pendingwith0700/0600permissions; pointOPENVIKING_PENDING_DIRelsewhere if that location does not suit your threat model.
Upstream & attribution
This package is derived from OpenViking's @openviking/dsh-memory-plugin
(Apache License 2.0), imported from a pinned upstream commit:
- Project: OpenViking
- Original package:
@openviking/dsh-memory-plugin(pathexamples/dsh-memory-plugin) - Original authors: OpenViking / Volcengine contributors
- Upstream revision:
688f78e923d2269d96c27096fe2dad10156ebdb8(version0.3.2) - License: Apache License 2.0 β see LICENSE
- Full provenance and the list of local modifications: UPSTREAM.md
- Upstream sync process: docs/upstream-sync.md
Files ported from upstream keep an attribution header naming the original project, and no upstream copyright or attribution notice was removed.
Compatibility
- DeepSeek Harness
>=0.1.5-rc.2 <0.2.0 - Node.js
^22.19.0 || >=24.0.0
See compatibility.json in the installed package for the machine-readable form.
Development
pnpm nx run @yadsh/dsh-openviking-memory:build
pnpm nx run @yadsh/dsh-openviking-memory:lint
pnpm nx run @yadsh/dsh-openviking-memory:typecheck
pnpm nx run @yadsh/dsh-openviking-memory:test
pnpm nx run @yadsh/dsh-openviking-memory:verify
The product contract lives in SPEC.md.
License
Apache License 2.0, inherited from the upstream package this fork is derived from. See LICENSE.