OpenViking × DeepSeek Harness 记忆插件接入指南:为 dsh 赋予跨项目长期记忆

【免费下载链接】OpenViking Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills. 【免费下载链接】OpenViking 项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

OpenViking 为 AI Agent 提供统一的自进化上下文数据库,而 DeepSeek Harness(dsh)作为 DeepSeek 官方的 Agent 开发工具,可以通过 @openviking/dsh-memory-plugin 插件获得跨项目、跨会话的长期记忆能力。本文以 docs/zh/agent-integrations/17-dsh.md 为骨架,结合 examples/dsh-memory-plugin 下的源码实现,完整讲解该插件的安装、验证、配置、运行机制与常见问题排查,让你能直接在自己的 DSH 环境中复现「每次对话自动召回相关记忆、自动捕获新内容,且模型直接拿到 OpenViking 工具与 openviking-memory 技能」的完整链路。

一、插件能做什么

dsh 插件以 Cordis 插件的形式跑在 DSH 进程内(而非外挂 hook),因此能紧密贴着会话生命周期工作,安装后无需额外配置即可获得四项核心能力:

  • 自动召回:每个模型步骤(pre-step)前用当前输入做语义检索,把结果作为持久消息追加到同一步骤;
  • 自动捕获:直接从 DSH 的事件流捕获 user、assistant 以及(可选的)工具结果消息,待同步 token 超过阈值即 commit,并保留最近十条消息在本地上下文中;
  • 工具面直通:模型看到的是 OpenViking 的完整 MCP 工具集,以 mcp__openviking__* 前缀发布,无需手工维护工具子集;
  • 技能注入:附带共享的 openviking-memory 技能,让模型知道何时该检索、读取和写入。

插件源码位于 examples/dsh-memory-plugin,以 npm 包 @openviking/dsh-memory-plugin 发布,运行时没有任何 npm 依赖——它的消息结构来自 @deepseek-ai/dsh-llm 的 createUserMessage,工具面来自 @deepseek-ai/dsh-mcp-client,技能提供来自 @deepseek-ai/dsh-skill-filesystem,这些 peerDependencies 由 DSH 自身安装,无需向 profile 额外添加任何东西(见 examples/dsh-memory-plugin/README.md)。

二、安装:两种方式任选

方式一:统一安装器(推荐)

DSH 与其他记忆插件(Claude Code、Codex、OpenCode、pi 等)共用同一个安装器。它会依次询问语言(English/中文)、要安装的 harness、下载源和 OpenViking 凭据;每一步都是幂等的,重复运行完全安全。

bash <(curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/examples/memory-plugin-shared/install.sh)

GitHub 访问困难的地区,可以从火山引擎 TOS 镜像运行同一个安装器(或在下载源选项里选「TOS 镜像」):

bash <(curl -fsSL https://ovrelease.tos-cn-beijing.volces.com/memory-plugin-shared/install.sh)

选择 DSH 后,安装器会询问装到哪个 profile,默认 web;也可以用 --dsh-profile <name> 提前指定。

安装完成后用一段时间,开一个新会话问问之前提过的事情——它会记得。

方式二:手动安装

  1. 配置连接:写 ~/.openviking/ovcli.conf(含 url、api_key,可选 account/user),或设置 OPENVIKING_URL 和 OPENVIKING_API_KEY 环境变量。如果使用纯本地模式(http://127.0.0.1:1933,无鉴权),这一步可以跳过——插件默认就指向本地。

  2. 把插件装进 profile:

    dsh plugin --profile web add @openviking/dsh-memory-plugin
    

    dsh plugin 会转发给 profile 目录下的 pnpm,所以任何 profile 名都可以;web 是 dsh 首次运行时自动创建的那个。注意:从源码 checkout 目录直接链接(dsh plugin --profile web add ./examples/dsh-memory-plugin)仅在 checkout 自带 node_modules 时可用,因为 Node 会从源码树的 realpath 解析 bundle 的 dsh peers,而不是从 profile 解析。

  3. 确认 profile 已生效:

    dsh --profile web --dump-config
    

    输出里应该能看到 openviking-memory 插件组。

还没有 ovcli.conf?见部署指南 → CLI。

卸载:dsh plugin --profile web rm @openviking/dsh-memory-plugin。

三、验证:启动、看注入、查召回

启动 dsh --profile web 打开一个会话,按以下三点确认插件生效:

  1. 上下文注入:会话开头应该能看到一条 OpenViking 上下文注入(形如 <openviking-context source="profile"> 的画像块);
  2. 工具可见:模型应该具备 mcp__openviking__* 工具;
  3. 召回生效:问一句更早会话里聊过的事,确认召回结果被注入。

如果什么都没有,设置 OV_DEBUG_LOG=/tmp/ov-dsh.log 后查看该文件。

从源码看,注入发生在 agent/session-start 与 agent/pre-step 两个事件上:index.mjs 中 injectStartupProfile 在会话启动时注入画像块,agent/pre-step 监听器以 { prepend: true } 注册,确保在其他贡献者之后追加画像与召回结果,且 profile 与 recall 通过 Promise.all 并发执行以减少瀑布等待时间。

四、工作方式:事件驱动、会话映射与工具面

4.1 生命周期与事件挂钩

插件的 apply() 在 index.mjs 中注册了完整的事件监听:

DSH 事件插件行为
agent/session-start注入 OpenViking 画像块与可用记忆索引
agent/pre-step用当前步骤输入做语义检索,把结果作为持久消息追加到同一步骤
session/event捕获 user、assistant 及(可选的)工具结果消息,并检查 token 阈值决定是否 commit
session/flush冲刷该会话的待写队列
tools/pre-execute拦截把 viking:// URI 当本地路径的 filesystem/shell 调用

注入选择 pre-step 用户消息而非 system prompt,是刻意设计:DSH 的 preset 若声明了 complete: true(如自带的 minimal preset),会在组装阶段把 persona 恢复为唯一 prompt 区块,静默丢弃其他贡献——基于 system prompt 的记忆插件在这种 preset 下会无提示地丢失上下文。而 pre-step 注入让每次注入都成为可重放、对压缩可见的会话事件(见 examples/dsh-memory-plugin/README.md 的设计说明)。

4.2 会话映射与 peer

每个 DSH 会话映射为 OpenViking 中的 dsh-<session-id>,子 agent 各自拥有独立会话。对应关系由 shared/session-model.mjs 的 deriveHarnessSessionId("dsh-", session.id) 生成,子 agent 会话可通过 skipSubagentSessions: true 排除(匹配 header.origin: subagent)。

4.3 MCP 工具面

模型看到的工具面就是 OpenViking 的 MCP 工具集,经由与其他记忆集成相同的 stdio 代理 servers/mcp-proxy.mjs 接入,以 mcp__openviking__ 前缀发布,包括 mcp__openviking__search、mcp__openviking__read、mcp__openviking__list、mcp__openviking__tree、mcp__openviking__grep、mcp__openviking__glob、mcp__openviking__remember、mcp__openviking__write、mcp__openviking__edit、mcp__openviking__forget、mcp__openviking__add_resource 以及服务器声明的其余工具。工具列表会在服务器通告变更时重新同步,因此服务器升级新增工具无需发新版 bundle。

为什么不直接让 DSH 连接服务器的 /mcp 端点?因为服务器在 stateless_http=True 时仍会以空闲 200 SSE 流响应 GET /mcp,一旦 MCP SDK 客户端打开这条独立流就不再解析 POST 响应,tools/list 永远不会返回;代理自己掌握传输层,不受影响(见 README 设计说明)。

由于代理每个 profile 只起一个进程,有两个直接后果:

  • actor peer 是进程级的:召回、捕获、commit 仍按每个会话从该会话的工作区仓库解析 peer,但工具调用携带的是启动时解析的 peer。若一个进程要服务多个工作区且需要精确归属工具调用,请显式设置 OPENVIKING_PEER_ID;
  • remember 不是会话级的:服务端 MCP 的 remember 写入的是服务端一个短生命周期的会话而非当前的 dsh-<session-id> 流(对话本身仍由自动捕获记录)。

MCP 桥接(mountOpenVikingMcp)与技能提供者(mountOpenVikingSkills)在 apply() 中最后挂载且不阻塞等待——因为桥接会阻塞在首次 tools/list 上,这样即使服务器连接受理但迟迟不响应,也不会拖住上面所有生命周期注册(见 index.mjs 注释)。

4.4 URI 拦截

误把 viking:// URI 当本地路径的文件或 shell 调用会被 tools/pre-execute 拦截(guardVikingUri),并提示改用对应的 OpenViking 工具。viking:// 是虚拟数据库路径而非文件系统路径,这一保护在 uri-guard.mjs 中实现。

4.5 写入失败重放

写入失败会进入共享的 OpenViking 待写队列(shared/pending-queue.mjs),在下次会话开始时重放(replayPending)。syncTurns: false 时重放同样被禁用——队列中的写入会一直保留,直到某个仍在写入的会话把它们排空。对应逻辑见 runtime.mjs 的 initializeState 与 enqueuePending。

五、配置详解

5.1 凭证解析顺序

凭证解析顺序为 OPENVIKING_* 环境变量 → ~/.openviking/ovcli.conf → ~/.openviking/ov.conf,与 Claude Code、Codex、OpenCode、pi 共用同一条链路(见 shared/credentials.mjs);这些文件变更后会自动重载。ov.conf 的 server 段(url/host/port/root_api_key)与 codex 段也会被读取。patch 中写的凭证优先于环境变量;行为开关则优先读环境变量。

环境变量默认值说明
OPENVIKING_URL / OPENVIKING_BASE_URLhttp://127.0.0.1:1933服务端点
OPENVIKING_API_KEY / OPENVIKING_BEARER_TOKEN—API Key(以 Authorization: Bearer 发送)
OPENVIKING_ACCOUNT / OPENVIKING_USER—可信模式下的 account 与 user
OPENVIKING_PEER_ID—显式指定 actor peer
OPENVIKING_WORKSPACE_PEERtrue按每个会话的工作区推导 peer;设为 0 则不发送 peer
OPENVIKING_RECALL_PEER_SCOPEall设为 actor 可将召回限制在当前工作区
OV_DEBUG_LOG—把调试日志写到该路径

MCP 代理的凭证通过子进程环境传递:DSH 会从继承的 env 中清洗凭证形态的变量名,且子进程看不到 Cordis patch,所以 mcp.mjs 的 buildMcpConfig 要把运行时已解析的 endpoint/apiKey/account/user/peerId 显式写入代理的子进程 env(DSH Desktop 下还需设置 ELECTRON_RUN_AS_NODE=1,让 Electron 以 Node 方式运行代理脚本)。

5.2 行为参数:Cordis patch

行为参数写在 profile 的 Cordis patch 条目里(模板见 cordis.patch.yml):

- insert:
    - id: openviking-memory
      name: '@deepseek-ai/cordis-plugin-group'
      group: true
      isolate:
        openvikingMemory: true
      config:
        - id: openviking-memory-runtime
          name: '@openviking/dsh-memory-plugin'
          config:
            endpoint: http://127.0.0.1:1933
            recallTokenBudget: 2000
            scoreThreshold: 0.35
            captureToolResults: false
            skipSubagentSessions: true
            commitTokenThreshold: 20000
            mcpToolCallTimeoutMs: 60000

所有配置项的默认值与边界约束都在 config.mjs 的 DEFAULT_CONFIG 与 clamp* 函数中定义,关键参数如下:

参数默认值约束范围说明
endpointhttp://127.0.0.1:1933—服务端点,结尾多余的 / 会被去除
recallTokenBudget2000200–50000单次召回的 token 预算
scoreThreshold0.350–1召回相似度阈值
recallLimit101–50召回结果条数上限
recallMaxContentChars500100–5000单条召回内容最大字符数
recallPreferAbstracttrue—优先返回摘要而非全文
minQueryLength31–64最短查询长度(低于此值不触发召回)
profileTokenBudget10000500–50000画像注入的 token 预算
commitTokenThreshold200001000–1000000触发 commit 的 pending token 阈值
commitKeepRecentCount100–1000commit 时保留在本地上下文的最近消息数
captureModesemanticsemantic/keyword捕获模式
captureMaxLength24000200–100000单条捕获内容最大长度
captureToolResultsfalse—是否捕获工具结果消息
captureAssistantTurnstrue—是否捕获 assistant 轮次
skipSubagentSessionsfalse—是否跳过 origin: subagent 的子 agent 会话
requestTimeoutMs100001000–120000普通请求超时
mcpToolCallTimeoutMs600001000–600000MCP 工具调用超时
syncTurnstrue—见下文「只读模式」

5.3 只读模式:syncTurns: false

同一个 config 块里的 syncTurns: false 让该集成变成只读:画像注入和记忆召回照常,但什么都不再写回——不捕获对话、不 commit,也不重放此前会话排入队列的写入,那些写入会一直留在队列里,直到某个仍在写入的会话把它们排空。源码层面,runtime.mjs 的 capture()、maybeCommit()、dispose() 均在开头检查 state.config.syncTurns,测试 runtime.test.mjs 的 syncTurns false sends nothing 用例验证了「无捕获、无 commit、无 dispose flush、无重放」的完整行为。

5.4 工作区 peer:peerSource

同一个 config 块里的 peerSource 决定工作区 peer 的派生方式(实现见 shared/workspace-peer.mjs):

  • "git"(默认):取仓库归一化后的 origin URL(git@github.com:volcengine/OpenViking.git 得到 github.com-volcengine-openviking),其次是仓库根路径,因此同一个仓库的每个 clone、worktree 和子目录共用同一个 peer;不在仓库中则完全不发送 peer,在那里记下的内容进入用户级空间 viking://user/<you>/memories;
  • "cwd":恢复此前的行为——把工作目录路径中的非字母数字字符全部替换成 -;
  • "none":完全不发送 peer。

peerSource 也接受模板字符串(如 "team-{dir}")或模板数组;拼写错误的 preset 名(不含 { 的裸字符串)会被警告并回退到默认链,避免产生一个无人预期的命名空间。

注意:DSH 不会读取工作区的 .openviking/config.json,所以写在里面的 peer.id 不生效;要让仓库之外的目录拥有独立记忆,请为它设置 OPENVIKING_PEER_ID(详见让一个目录拥有独立记忆)。旧版基于路径的 peer 下写入的记忆仍可被召回到:默认的 recallPeerScope: all 会扫遍用户下的所有 peer,且 resolveEffectivePeerId 返回的 legacyPeerId 会让召回同时命中旧命名空间。

5.5 技能注入

插件通过自己的独立 ctx.skills 提供者(includeDefaultRoots: false)只挂载 skills/openviking-memory/SKILL.md,不会遮蔽或复制 DSH 自带的 filesystem 技能目录。技能内容指导模型:会话生命周期(启动注入、任务中检索、有持久信息时写入、结束时自动捕获 commit)、检索工具选择(search 的 context 模式优先、find 快速三选、grep/glob 精确匹配)、写入纪律(remember 只用于用户明确要求保留或明确的持久事实;forget 是永久删除,仅当用户明确要求时使用;viking:// URI 是虚拟路径,绝不能传给 filesystem 工具)。

六、版本与运行前提

从 examples/dsh-memory-plugin/README.md 的 Requirements 可以确认:

  • @deepseek-ai/dsh 需要 0.1.0-rc.6 或更新的 0.1.x 版本(peer 范围止于 0.2.0 之前);
  • Node.js 需要 ^22.19.0 或 >=24;
  • 需要一个可达的 OpenViking 服务器,且服务器须支持 viking://~ home-alias(召回面向调用者自身的 viking://~/memories 与 viking://~/skills 空间)。

自测方式:在插件目录运行 npm ci 安装精确锁定的 dsh devDependencies、npm run check 做语法与版本一致性检查、npm test 运行全部单元测试;live-recall.test.mjs 是可选的真服务器端到端闸门,用 OPENVIKING_E2E=1 加正常凭证链启用——它通过会话 commit 存入哨兵记忆,等待抽取后断言召回能取回该哨兵,这是任何 stub 都无法验证的性质。

七、常见问题排查

现象排查方向
没有注入,也没有 OpenViking 工具dsh --profile web --dump-config 里应能看到 openviking-memory;重新运行安装器或 dsh plugin --profile web add …
装到了错误的 profile安装器默认 web;用 --dsh-profile <name> 重新运行
安装时报 ERESOLVE@deepseek-ai/dsh-* 各包预发布 tag 不同步;请精确安装 @deepseek-ai/dsh@0.1.0-rc.6
安装时报包「不在 npm registry 中」pnpm 默认拒绝发布不满 24 小时的版本(minimumReleaseAge)。等一等,或把该精确版本加进 profile 的 pnpm-workspace.yaml 的 minimumReleaseAgeExclude
召不回任何内容curl http://localhost:1933/health;检查端点配置,以及 prompt 是否长于最小查询长度(3 个字符)
OpenViking 返回 401 / 403检查 OPENVIKING_API_KEY;可信模式部署还要检查 OPENVIKING_ACCOUNT 与 OPENVIKING_USER
串入了其他项目的记忆设置 OPENVIKING_RECALL_PEER_SCOPE=actor
崩溃后没有 commitcommit 由 token 阈值和 teardown 触发;排队的写入会在下次会话开始时重放

八、延伸阅读

【免费下载链接】OpenViking Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills. 【免费下载链接】OpenViking 项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐