dsh-openviking-autostart
DSH OpenViking 自动启动与恢复插件:会话前确保本机记忆服务可用。
- Stars
- 0
- Language
- JavaScript
- Created
- Oct 22, 2026
- Updated
- Oct 22, 2026
Introduction
dsh-openviking-autostart
DSH 宿主平面 Cordis 插件(profile bundle):新会话开始前先确认 OpenViking 服务在运行,没运行就先拉起,再执行任务。
它解决什么
本机把 OpenViking 当作 DSH 的长期记忆服务。手工启动 DSH Web 时,如果忘了开 OpenViking,整个会话都在"记忆离线"状态下进行:召回为空、写入进离线队列——等发现时已经过去很久。
这个插件把这件事变成机制,而不是每次靠人记得:
| 会话开始时的状态 | 行为 |
|---|---|
| OpenViking 在运行 | 毫秒级探测通过,直接执行任务 |
| OpenViking 没运行 | 用现成启动脚本拉起,就绪后再执行任务(readyTimeoutMs 是整次尝试的总预算;代码默认 8 秒,本机 row 按实测冷启动约 19 秒调成 30 秒) |
| OpenViking 拉不起来 | 记录警告,照常执行任务(写入进离线队列,服务起来后自动补) |
| 没装 OpenViking 插件 | 插件根本不激活:不探测、不拉起、直接执行任务 |
最后一行不是"我们的代码里写了个 if",而是 Cordis 的运行时不变量——见下节。
会话侧最坏情况:readyTimeoutMs + 一次探测超时(代码默认约 9.5 秒;本机 row 取 30000 时为约 31.5 秒,且 cooldownMs 保证同一时间窗内不会反复等)。额外的这一次是收尾探测——循环在 deadline 前发起的最后一次探测仍要走完自己的超时。
为什么"没装插件就不激活"是硬保证
@openviking/dsh-memory-plugin 在自己的 apply() 里发布宿主服务:
ctx.provide("openvikingMemory", runtime);
本插件声明:
export const inject = ['openvikingMemory'];
Cordis 只有在注入全部满足时才会执行 apply()(Fiber._refresh() 对缺失的服务强制 INACTIVE epoch,_reload() 不会运行)。因此把 OpenViking 插件卸载、或把它的行设为 disabled 之后,本插件不会被加载,一行代码都不会跑。
这条依赖同时写在 cordis.patch.yml 的行元数据里,所以 dsh --profile web --dump-config 能直接看到它。
安装与卸载
# 安装(profile 级 bundle;本机 profile 是 web)
dsh plugin --profile web add "C:\Users\a1941\Desktop\DeepSeek\dsh-openviking-autostart"
# 卸载:行与依赖一起消失,工作区内零残留
dsh plugin --profile web remove dsh-openviking-autostart
装完后重启 DSH Web 生效(新装的 bundle 也可能通过 HMR 直接生效,以 --dump-config 与日志为准)。
认证与验收
npm test # 61 个用例:决策核心、配置、端点、探测、启动器、装配
npm run verify # 三条验收:组合层 + 真实 Cordis 激活门 + 启动器定位
| 脚本 | 验证什么 |
|---|---|
node verify/composition.mjs | 行真的进了 profile:dsh --profile web --dump-config 退出码 0,含本行与 openvikingMemory 注入 |
node verify/activation.mjs | 用真实 Cordis 跑正/反两个对照:有 openvikingMemory 才 apply,没有就完全不加载 |
node verify/launcher.mjs | 按 patch 里实际生效的配置解析启动器并确认文件存在(不执行它) |
三个脚本都不需要 OpenViking 服务在运行。
真实验收(服务关着 → 新会话 → 被自动拉起;会短暂停掉本机记忆服务,写入进离线队列不会丢):
# 1. 停服
& "C:\Users\a1941\Desktop\DeepSeek\dsh-web-openviking\stop-openviking.ps1"
# 2. 在 DSH Web 里新建一个会话(触发 agent/created)
# 3. 验证
netstat -ano | findstr ":1933 .*LISTENING"
(Invoke-WebRequest http://127.0.0.1:1933/api/v1/system/status -UseBasicParsing).StatusCode
配置
全部通过本 bundle 的 cordis.patch.yml(升级不丢)。默认值即为上表行为;不配也能用。
| 键 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
endpoint | 空 | 端点覆盖;空则读 ~/.openviking/ovcli.conf 的 url → OPENVIKING_URL → 127.0.0.1:1933 |
startCommand | 空 | 启动器覆盖;空则 OPENVIKING_START_SCRIPT → 在 searchRoots 下查找内置启动器 |
searchRoots | [工作区根] | 查找启动器的目录列表(shipped patch 里钉成 Desktop\DeepSeek);[] = 不查找 |
probeTimeoutMs | 1500 | 单次存活探测上限 |
readyTimeoutMs | 8000(代码默认;本机 row 为 30000) | 整次尝试的总预算(拉起 + 等待就绪);超出即放行,会话最多多等 readyTimeoutMs + probeTimeoutMs |
cooldownMs | 60000 | 拉起失败后的抑制窗口,防并发会话把启动器踩爆 |
sources | [startup, resume] | 触发检查的会话来源 |
logLevel | info | 本插件日志级别 |
为什么 clear / compact 不触发检查
agent/created 的 source 实测取值(dsh-agent/lib/types/runtime-types.d.ts):
startup —— 全新会话
resume —— 重新打开已持久化的会话
clear —— 在一个进行中的会话内部清空重建
compact —— 在一个进行中的会话内部压缩重建
clear / compact 时服务按定义已经在运行,而且那是用户没要求的操作——为一个内部重建插入等待没有意义。要改就改 sources,别改代码。
sources 是白名单:只有列出的来源才触发检查,没列出的(包括将来 DSH 新增的来源名)一律跳过,跳过时留一行 debug 日志。这样 DSH 改版新增会话来源时不会静默地开始启动进程。
设计要点
在 agent/created 上等待,而不是在 DSH 启动时检查。
该事件由 dsh-agent 的 announce() 串行且 await 派发:监听器返回之前,会话创建不完成。所以"先拉起、再执行任务"是由事件语义保证的,不是靠抢时序。DSH 启动本身不做任何阻塞。
复用现成的启动器,不重新实现拉起。
dsh-web-openviking\start-openviking.cmd 已经处理了本机的硬事实:数据目录必须钉在工作区根(换个 cwd 会静默生成第二个空库)、必须用 python -m openviking_cli.server_bootstrap(uv 壳会留下半死的父进程并让两个进程抢 vectordb 锁)、启动前清理残留服务进程。插件只负责"该不该拉"和"拉到没拉起来"。
探测只问"HTTP 有没有响应"。 任何状态码都算活着——401/404 同样证明端口后有服务在路由。问的是进程存活,不是授权,所以探测不带凭据,也不走 OpenViking 客户端(客户端带重试与队列策略,会把记忆层策略混进存活判断)。
三条硬性质(由 test/ 锁定):
- 任何路径都不抛错——记忆服务起不来不是拒绝用户任务的理由;
- 任何路径都有界——不会有一个会话被起不来的服务卡住;
- 并发会话最多拉起一次——单飞 + 冷却,避免多个会话同时抢启动。
明确不做的事
- 不改 DSH 安装目录、不改 System Prompt、不加工具、不写会话事件;
- 不碰 OpenViking 的看门狗 lock,也不默认传
/bind(生命周期绑定是你已有的独立机制); - 不做"DSH 启动时预热"(那会在用户没要求的时候动进程)。
结构
| 文件 | 职责 |
|---|---|
lib/index.mjs | Cordis 装配:注册 agent/created 监听 |
lib/ensure.mjs | 决策与编排核心(副作用全部注入,可单测) |
lib/config.mjs | 配置归一化 + shouldCheckSource |
lib/endpoint.mjs | 端点发现 |
lib/probe.mjs | 单次有界存活探测 |
lib/launcher.mjs | 启动器定位(纯)+ 唯一的进程启动副作用 |
test/ | 61 个离线用例 |
verify/ | 组合层与启动器验收(需要 DSH) |
许可
Apache-2.0。