# OpenViking

> Inject OpenViking long-term memory into DSH: automatically recall relevant context before each step, asynchronously persist the entire conversation to disk, and provide the mcp__openviking__* toolset with viking:// URI protection.

## Metadata

- Author: [@volcengine](https://github.com/volcengine)
- Repo: <https://github.com/volcengine/OpenViking.git>
- GitHub: [volcengine/OpenViking](https://github.com/volcengine/OpenViking)
- Stars: 30,827
- Language: Python
- License: [AGPL-3.0](https://spdx.org/licenses/AGPL-3.0.html)
- Homepage: <https://openviking.ai/>
- Topics: `agent-memory`, `agent-plugins`, `agentic-rag`, `context-database`, `dsh-plugin`, `self-evolving`
- Forks: 2,376
- Open Issues: 472
- Last push: 2026-08-20T13:52:55.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:volcengine/OpenViking/examples/dsh-memory-plugin
```

## Wiki

## 一句话定位
为 DeepSeek Harness 接入 OpenViking 上下文数据库：在每一步前自动检索相关记忆，整段对话异步落盘，并向模型暴露 `mcp__openviking__*` 工具集与一份 `openviking-memory` 技能指导。

## 核心能力
- 在 `agent/pre-step` 钩子用当前步骤的输入做语义检索，把命中结果追加为带来源标注的 user message，作为后续回答的背景
- 监听 `session/event` 自动采集用户、助手与（可选）工具结果消息并写入 OpenViking session，达到 token 阈值时自动 commit
- 注册一套桥接后的模型工具：`mcp__openviking__search` / `read` / `list` / `tree` / `grep` / `glob` / `remember` / `write` / `edit` / `forget` / `add_resource` 等（随服务端广告自动同步）
- 在 `tools/pre-execute` 拦截 DSH 本地工具对 `viking://` URI 的错误调用，让模型改走桥接的 OpenViking 工具
- 单独挂一个 `openviking` 技能 provider，只服务内置的 `openviking-memory` 技能，与 DSH 自带的文件系统 provider 互不干扰
- 服务端临时不可达时自动回落到本地待写队列（`~/.openviking/pending/`），下个会话启动时 replay
- 每个 DSH session 映射为 `dsh-<session-id>`；actor peer 默认从工作目录派生，可显式覆盖

## 技术实现
- **语言**: JavaScript（Node.js ESM，纯 `*.mjs`）
- **关键依赖**: `@deepseek-ai/dsh-llm`（`createUserMessage` 构造注入消息）、`@deepseek-ai/dsh-mcp-client`（挂 MCP 桥接）、`@deepseek-ai/dsh-skill-filesystem`（挂技能 provider）
- **架构模式**: Cordis 插件组（`@deepseek-ai/cordis-plugin-group`），`apply(ctx, input)` 内部订阅 `agent/session-start` / `agent/pre-step` / `session/event` / `session/flush` / `tools/pre-execute` 五个生命周期事件；MCP 桥接以 stdio 子进程拉起 `servers/mcp-proxy.mjs`，避免直接连 `/mcp` 时的连接卡死
- **入口文件**: `examples/dsh-memory-plugin/index.mjs`，由 `cordis.patch.yml` 声明装载

## 适用场景
需要让 DSH 在多会话、多工作区里复用过往项目知识与用户偏好的开发者：模型每轮会自动从历史决策、文档里检索上下文，同时把对话异步落到 OpenViking 服务端，避免下次又得重新交代；你也可以通过 `add_resource` 把远程仓库或文档一次性灌进 `viking://` 虚拟文件系统。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH（`@deepseek-ai/dsh-llm`、`dsh-mcp-client`、`dsh-skill-filesystem`） | `>=0.1.0-rc.6 <0.2.0` | peerDependencies 锁定 0.1.x 范围，0.2.x 上无法装载 |
| Node.js | `^22.19.0 || >=24` | engines 字段硬性要求，更早版本直接拒绝 |
| 平台 | 跨平台 | 源码未声明 `os` / `cpu` 限制 |
| 原生模块 | 无 | bundle 本身无运行时 npm 依赖；只用 Node 内置 `fs`/`os`/`crypto`/`url` |

## 安装方式
```bash
dsh plugin --profile web add github:volcengine/OpenViking/examples/dsh-memory-plugin
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| `endpoint` | string | OpenViking 服务地址 | `http://127.0.0.1:1933` |
| `apiKey` | string | Bearer 凭证（也支持 `OPENVIKING_API_KEY` / `OPENVIKING_BEARER_TOKEN`，或写在 `~/.openviking/ovcli.conf`） | `""` |
| `account` | string | trusted-mode 账号（请求头 `X-OpenViking-Account`） | `""` |
| `user` | string | trusted-mode 用户（请求头 `X-OpenViking-User`） | `""` |
| `peerId` | string | 显式 actor peer，覆盖从工作区派生的默认值 | `""` |
| `workspacePeer` | boolean | 是否从当前工作目录自动派生 actor peer | `true` |
| `recallPeerScope` | `"all"` \| `"actor"` | 召回时是否限制在当前 peer 内 | `all` |
| `recallQueryExpansion` | `"auto"` \| `"off"` | 是否对查询做改写 | `auto` |
| `recallTokenBudget` | number (200–50000) | 召回上下文允许占用的最大 token | `2000` |
| `recallMaxContentChars` | number (100–5000) | 召回条目 abstract 截断长度 | `500` |
| `recallLimit` | number (1–50) | 召回条数 | `10` |
| `scoreThreshold` | number (0–1) | 召回分数阈值，低于此值的命中会被丢弃 | `0.35` |
| `minQueryLength` | number (1–64) | 触发召回的最短 query 长度 | `3` |
| `profileTokenBudget` | number (500–50000) | 启动时一次性注入 profile 的 token 上限 | `10000` |
| `commitTokenThreshold` | number (1000–1000000) | 累计 pending token 达到该值时触发 session commit | `20000` |
| `commitKeepRecentCount` | number (0–1000) | commit 时保留的最近消息条数 | `10` |
| `captureMode` | `"semantic"` \| `"keyword"` | 自动采集模式 | `semantic` |
| `captureAssistantTurns` | boolean | 是否把助手回复一起采集 | `true` |
| `captureToolResults` | boolean | 是否采集工具执行结果 | `false` |
| `captureMaxLength` | number (200–100000) | 单条采集消息的最大长度 | `24000` |
| `captureToolMaxChars` | number (200–1000000) | 工具结果允许的最大字符数 | `1000000` |
| `requestTimeoutMs` | number (1000–120000) | 调 OpenViking HTTP 接口的超时 | `10000` |
| `mcpToolCallTimeoutMs` | number (1000–600000) | 桥接 MCP 工具调用超时 | `60000` |

> 凭证查找顺序：环境变量（`OPENVIKING_URL` / `OPENVIKING_API_KEY` / `OPENVIKING_BEARER_TOKEN` / `OPENVIKING_ACCOUNT` / `OPENVIKING_USER` / `OPENVIKING_PEER_ID` / `OPENVIKING_CREDENTIAL_SOURCE` / `OPENVIKING_CONFIG_FILE` / `OPENVIKING_CLI_CONFIG_FILE`）→ `~/.openviking/ovcli.conf` → `~/.openviking/ov.conf` → 内置默认（`http://127.0.0.1:1933`）。
> 待写队列环境变量：`OPENVIKING_PENDING_DIR`（默认 `~/.openviking/pending/`，目录权限 0o700、文件 0o600）、`OPENVIKING_PENDING_MAX_RETRIES`（默认 3）、`OPENVIKING_PENDING_TTL_DAYS`（默认 7）、`OPENVIKING_PENDING_REPLAY_LIMIT`（默认 50）。

## 常见问题

**Q: 安装后默认连接哪个 OpenViking 服务？**

A: 默认连本机的 `http://127.0.0.1:1933`。可通过 `OPENVIKING_URL` 环境变量、`~/.openviking/ovcli.conf` 配置文件，或在 `cordis.patch.yml` 的 `config.endpoint` 字段显式覆盖。

**Q: 需要 DSH 哪个版本？**

A: 需要 DSH `0.1.0-rc.6` 及以上的 `0.1.x`。`package.json` 把核心 peer 包锁在 `>=0.1.0-rc.6 <0.2.0`，跨到 `0.2.x` 会因 peerDependencies 不匹配而装载失败。

**Q: 离线时对话会不会丢？**

A: 不会。OpenViking 服务不可达或写失败时（HTTP 408 / 429 / 5xx，或返回 `retryable: true`），消息会被序列化进 `~/.openviking/pending/`（目录权限 `0o700`、文件 `0o600`），下个会话启动自动 replay；最多重试 3 次或 7 天后清理。

**Q: `viking://` 是什么？DSH 自带的 `read` 工具能直接打开吗？**

A: `viking://` 是 OpenViking 的虚拟数据库 URI，不是本地文件路径。插件在 `tools/pre-execute` 阶段会拦截 DSH 的 `read` / `glob` / `grep` / `bash` / `edit` / `write` / `str_replace_editor` 对 `viking://` 的错误调用，把模型引导到 `mcp__openviking__read` / `mcp__openviking__list` / `mcp__openviking__grep` 等桥接工具。

**Q: 卸载插件后记忆会被清掉吗？**

A: 不会。记忆保存在 OpenViking 服务端，卸载插件只会停止自动召回与采集，不会删除已落盘的数据；要彻底删除，调 `mcp__openviking__forget` 并传准确的 `viking://` URI。

**Q: 需要安装 OpenViking 服务端吗？**

A: 是的。插件只是客户端桥，必须有一个可达的 OpenViking 服务端才能完成召回与写入；服务端不可达时所有写操作都会回落到本地待写队列。

**Q: 是否需要配置 API Key？**

A: 不强制。本地默认配置下空 key 也能连到本地服务；接入远程服务或 trusted-mode 部署时，需设置 `OPENVIKING_API_KEY`（或 `OPENVIKING_BEARER_TOKEN`），并按需配上 `OPENVIKING_ACCOUNT` / `OPENVIKING_USER`。

## 上手难度
进阶 — 安装只是单条 `dsh plugin add` 命令，但要真正用起来得先在本地或远端跑一个可达的 OpenViking 服务端，再理解 `viking://` URI、actor peer 隔离、召回预算等概念；如果只是看 README 就调配置项而不实际联调服务端，会被本地默认的 `127.0.0.1:1933` 拦在门外。

## 已知问题与限制
- 强绑定 DSH `0.1.x`：`peerDependencies` 把 `dsh-llm` / `dsh-mcp-client` / `dsh-skill-filesystem` 全部锁在 `>=0.1.0-rc.6 <0.2.0`，`overrides` 进一步把整个 dsh 家族固定到 `0.1.0-rc.6`，DSH 升级到 `0.2.x` 后本插件会因 peer 不匹配而无法装载。
- 强绑定 Node 引擎：`engines.node` 写死 `^22.19.0 || >=24`，更早的 Node 会直接拒绝安装。
- actor peer 的作用域仅限进程级：MCP 工具调用携带的是进程启动时解析的 peer，而不是每次请求重新解析；当一个进程服务多个 workspace 时，需要用 `OPENVIKING_PEER_ID` 显式覆盖。
- `mcp__openviking__remember` 不绑定当前 DSH 会话：服务端把 `remember` 写到自己的短期 session，而不是 `dsh-<session-id>` 实时流；自动采集仍然会落盘这条对话本身。
- 注入位置是 `agent/pre-step` 而非系统提示：设计本意是规避 `complete: true` preset 抹掉其它 prompt section 的问题；如果未来 DSH 在 `pre-step` 之后加入 strip-plugin-source 过滤器，召回上下文会被一并剥掉。
- `mcp__openviking__forget` 是不可逆的硬删除，README 明确要求模型只在用户明确请求时调用。
- 离线待写队列没有后台 worker：replay 只在下一次 session-start 触发，且单次最多 replay 50 条；如果服务长时间不可达，TTL（默认 7 天）或重试上限（默认 3 次）达到后条目会被清理。
- `live-recall.test.mjs` 端到端用例默认跳过：只有设置 `OPENVIKING_E2E=1` 且提供真实服务端凭证才会运行，CI 中目前未启用。

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [OpenViking](https://deepseek-plugin.org/plugins/volcengine/OpenViking/examples/dsh-memory-plugin)
Wiki generated by AI (model: `MiniMax-M3`)
