🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

多机运维台 wisp-science/WispOps

DeepSeek Harness
wisp-science5 天前有提交已提供中文文档扫描:含敏感能力

WispOps(dsh-wisp-ops):DeepSeek Harness 的多主机服务器运维插件——集群巡检、磁盘与近期文件分析(含组学数据清理建议)、安全排查、按服务器定时生成报告、人工审批的 sudo

31.1/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add wisp-science/WispOps
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · market
装得上吗
实装验证未通过(node_version),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(node_version · 2026/10/29) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 58 处,展示前 56 条)
  • 读取本地文件
    lib/inventory.js:32
    text = await readFile(expandHome(path), 'utf8');
  • 读取本地文件
    lib/service.js:49
    const mtime = (await Promise.all(paths.map(path => stat(path).then(s => `${s.mtimeMs}:${s.ctimeMs}:${s.size}`, error => {
  • 读取本地文件
    lib/skills.js:26
    const candidates = readdirSync(root, { withFileTypes: true })
  • 读取本地文件
    lib/skills.js:31
    const { name, description } = parseSkill(readFileSync(path, 'utf8'), path);
  • 读取本地文件
    lib/skills.js:50
    const raw = await readFile(locator, { encoding: 'utf8', signal: options.signal });
  • 读取本地文件
    lib/wispterm.js:37
    const text = await readFile(join(dir, 'passwords'), 'utf8');
  • 执行外部命令来自配置/变量
    lib/wispterm.js:67
    execFile(file, args, { encoding: 'buffer', timeout: 120_000, ...env === undefined ? {} : { env: { ...process.env, ...env } } }, (error, stdout) => {
  • 读取本地文件
    lib/wispterm.js:104
    const key = await readFile(join(dir, 'passwords.key'));
  • 读取本地文件
    lib/wispterm.js:199
    return parseSshHosts(await readFile(join(dir, 'ssh_hosts'), 'utf8'));
  • 执行外部命令来自配置/变量
    lib/vault.js:11
    const child = spawn(file, args, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 120_000 });
  • 读取本地文件
    lib/vault.js:37
    let stored = await readFile(file).catch(error => { if (error.code === 'ENOENT')
  • 写入本地文件
    lib/vault.js:44
    await writeFile(file, stored, { mode: 0o600, flag: 'wx' });
  • 写入本地文件
    lib/vault.js:48
    await chmod(file, 0o600);
  • 写入本地文件
    lib/ssh.js:164
    await chmod(dir, 0o700);
  • 写入本地文件
    lib/ssh.js:166
    await writeFile(passfile, password, { mode: 0o600 });
  • 写入本地文件
    lib/ssh.js:170
    await writeFile(script, `@type "${passfile}"\r\n`, { mode: 0o700 });
  • 写入本地文件
    lib/ssh.js:174
    await writeFile(script, `#!/bin/sh\ncat ${shellQuote(passfile)}\n`, { mode: 0o700 });
  • 删除本地文件递归
    lib/ssh.js:178
    cleanup: () => rm(dir, { recursive: true, force: true }),
  • 写入本地文件
    lib/ssh.js:192
    mkdirSync(this.controlDir, { recursive: true, mode: 0o700 });
  • 执行外部命令来自配置/变量
    lib/ssh.js:280
    const child = spawn(this.spec.binary, this.argv(host, request.sudo, withPassword), {
  • 读取本地文件
    lib/store.js:12
    text = await readFile(path, 'utf8');
  • 写入本地文件
    lib/store.js:97
    await mkdir(path, { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/store.js:104
    await writeFile(tmp, kept.map(r => JSON.stringify(r)).join('\n') + '\n', { mode: 0o600 });
  • 写入本地文件
    lib/store.js:105
    await rename(tmp, file);
  • 写入本地文件
    lib/store.js:110
    await appendFile(join(dir, `${month}.jsonl`), `${JSON.stringify(entry)}\n`, { mode: 0o600 });
  • 读取本地文件
    lib/store.js:121
    const names = (await readdir(join(this.dir, 'audit')).catch((error) => {
  • 删除本地文件
    lib/store.js:127
    await rm(join(this.dir, 'audit', name), { force: true });
  • 读取本地文件
    lib/store.js:133
    const names = (await readdir(join(this.dir, 'audit')).catch((error) => {
  • 写入本地文件
    lib/store.js:158
    await appendFile(file, `${JSON.stringify(record)}\n`, { mode: 0o600 });
  • 读取本地文件
    lib/store.js:191
    return JSON.parse(await readFile(join(this.dir, 'probes.json'), 'utf8'));
  • 写入本地文件
    lib/store.js:203
    await writeFile(tmp, JSON.stringify(merged, null, 2), { mode: 0o600 });
  • 读取本地文件
    lib/local-state.js:15
    return await readFile(this.path, 'utf8').catch(error => {
  • 写入本地文件
    lib/local-state.js:30
    await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/local-state.js:32
    await mkdir(lock, { mode: 0o700 }).catch(error => {
  • 写入本地文件
    lib/local-state.js:45
    await writeFile(temp, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600, flag: 'wx' });
  • 写入本地文件
    lib/local-state.js:46
    await chmod(temp, 0o600);
  • 写入本地文件
    lib/local-state.js:50
    await rename(temp, this.path);
  • 删除本地文件
    lib/local-state.js:64
    await rm(this.path, { force: true });
  • 写入本地文件
    lib/local-state.js:66
    await writeFile(temp, previous, { mode: 0o600, flag: 'wx' });
  • 删除本地文件
    lib/local-state.js:77
    await rm(temp, { force: true });
  • 删除本地文件递归
    lib/local-state.js:78
    await rm(lock, { recursive: true, force: true });
  • 读取本地文件
    lib/ssh-config.js:95
    text = await readFile(file, 'utf8');
  • 读取本地文件
    lib/ssh-config.js:119
    const names = await readdir(dir).catch(() => []);
  • 写入本地文件
    lib/sync.js:137
    await mkdir(dir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/sync.js:139
    await writeFile(join(dir, backupName), await sealSync(backup.snapshot, passphrase), { mode: 0o600, flag: 'wx' });
  • 写入本地文件
    lib/sync.js:142
    await mkdir(keyDir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/sync.js:145
    await writeFile(path, key.content, { mode: 0o600, flag: 'wx' }).catch(async (error) => {
  • 读取本地文件
    lib/sync.js:146
    if (error.code !== 'EEXIST' || !(await lstat(path)).isFile() || await readFile(path, 'utf8') !== key.content)
  • 读取本地文件
    lib/sync.js:146
    if (error.code !== 'EEXIST' || !(await lstat(path)).isFile() || await readFile(path, 'utf8') !== key.content)
  • 写入本地文件
    lib/sync.js:149
    await chmod(path, 0o600);
  • 读取本地文件
    lib/updates.js:42
    return this.runningVersion ??= readFile(join(this.root, 'package.json'), 'utf8').then(text => String(JSON.parse(text).version));
  • 读取本地文件
    lib/updates.js:121
    if (await stat(join(this.root, '.git')).then(() => true, () => false))
  • 发起网络请求
    lib/webdav.js:47
    const response = await this.request('PROPFIND', '', '<?xml version="1.0"?><d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/></d:prop></d:propfind>',
  • 发起网络请求
    lib/webdav.js:74
    const collection = await this.request('MKCOL');
  • 发起网络请求
    lib/webdav.js:78
    const response = await this.request('PUT', name, body, { 'content-type': 'application/json', 'if-none-match': '*' });
  • 发起网络请求
    lib/webdav.js:84
    const response = await this.request('GET', name);
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-api-gateway@deepseek-ai/dsh-api-remote-access@deepseek-ai/dsh-commands@deepseek-ai/dsh-llm@deepseek-ai/dsh-skill@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools@deepseek-ai/dsh-typert-protocol@deepseek-ai/dsh-typert-registry@deepseek-ai/dsh-user-approval@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
中文 · English WispOps(dsh-wisp-ops) DeepSeek Harness 的多主机服务器运维插件:服务器管理、独立加密密码库、按服务器的例行任务,以及巡检、磁盘诊断、安全排查和批量命令。变更、sudo、破坏性操作逐主机授权;密码只交给 SSH,不返回给页面或模型。不需要 WispTerm。 安装 需要 DeepSeek Harness >=0.2.1-rc.3 <0.3.0。推荐使用 npm 版:直接下载已打包的发行版本,安装更方便,无需访问 GitHub。npm 和 GitHub 是同一插件的两种安装来源,选择一种即可,均无需本地编译。 方式一:npm 版(推荐) 在终端中安装 npm 最新稳定版: dsh plugin --profile desktop add dsh-wisp-ops@latest 需要固定版本时,例如安装 0.13.0: dsh plugin --profile desktop add dsh-wisp-ops@0.13.0 desktop 是桌面版的默认 profile;Web 版通常改为 web。安装完成后重启 Harness,确认插件已启用。 方式二:GitHub 版 此方式需要能访问 GitHub,支持从插件页面或命令行安装。
展开完整文档(README 剩余 1 节)
中文 · English

WispOps(dsh-wisp-ops)

DeepSeek Harness 的多主机服务器运维插件:服务器管理、独立加密密码库、按服务器的例行任务,以及巡检、磁盘诊断、安全排查和批量命令。变更、sudo、破坏性操作逐主机授权;密码只交给 SSH,不返回给页面或模型。不需要 WispTerm。

安装

需要 DeepSeek Harness >=0.2.1-rc.3 <0.3.0。推荐使用 npm 版:直接下载已打包的发行版本,安装更方便,无需访问 GitHub。npm 和 GitHub 是同一插件的两种安装来源,选择一种即可,均无需本地编译。

方式一:npm 版(推荐)

在终端中安装 npm 最新稳定版:

dsh plugin --profile desktop add dsh-wisp-ops@latest

需要固定版本时,例如安装 0.13.0:

dsh plugin --profile desktop add dsh-wisp-ops@0.13.0

desktop 是桌面版的默认 profile;Web 版通常改为 web。安装完成后重启 Harness,确认插件已启用。

方式二:GitHub 版

此方式需要能访问 GitHub,支持从插件页面或命令行安装。

插件页面安装:

1. Harness 左侧 插件 → + 添加插件,粘贴 https://github.com/wisp-science/WispOps。
2. 安装源:国内网络选 中国大陆镜像源,其他选 npm 官方源。此选项只影响依赖下载,插件本身仍从 GitHub 获取。
3. 点击 安装,确认插件已启用。
4. 完全退出并重新打开 Harness。

命令行安装:

dsh plugin --profile desktop add github:wisp-science/WispOps

安装完成后重启 Harness。

升级与切换来源

- npm 版:重新执行上面的 @latest 命令升级,或指定要安装的版本。
- GitHub 版:在运维面板的 版本更新 中检查并安装稳定 Release,也可开启自动更新。面板内更新目前仅支持 GitHub 来源。
- Windows 从 GitHub 切换到 npm:先完全退出 Harness(含托盘),再从外部 PowerShell 执行 npm 版安装命令,完成后重开。遇到 EPERM rename 时见恢复步骤。

两种来源使用相同的包名和安装目录。服务器、密码库和任务默认保存在 ~/.dsh-wisp-ops/,卸载重装不会删除这个目录。本地开发链接不会被面板更新覆盖。

本地源码安装和常见报错见 docs/install.md。

上手

打开左侧 服务器运维(或会话右侧栏 开始 → 服务器运维):

1. 服务器:添加地址、用户名和端口,或从 ~/.ssh/config 批量导入;保存后自动探测能力。不需要的 WispTerm / 配置服务器可从 WispOps 移除,并从“已移除”列表恢复,原始配置保留。
2. 密码库:新建凭据,只填名称和密码。再到服务器详情为 SSH 登录、sudo 提权分别关联凭据,可先测试再保存。密钥登录、免密 sudo 可跳过。
3. 任务库:选择内置模板或自建,点击 关联服务器,设置检查对象和运行时间。
4. 例行任务:选择接收报告的会话,点击 运行一次 立即执行看效果,或点击 启用调度 定时运行。Harness 需保持运行;漏跑的任务会在卡片上标出。
5. 操作审计:查看模型、面板和任务执行过的每条远程命令及其授权和结果。

也可以手写 ~/.dsh-wisp-ops/inventory.yml,参考 examples/inventory.yml。

能做什么

| 工具 | 用途 |
| ops_inspect | 巡检负载、内存、磁盘、systemd、GPU、Slurm、OOM 等,按阈值告警并与上次对比 |
| ops_disk | 磁盘诊断:大目录和大文件、是否被进程或作业占用、已删除仍占用的空间、各类缓存 |
| ops_files | 近期新增文件:按目录和属主统计,识别测序/生信文件并生成清理计划 |
| ops_security | 攻击排查:SSH 暴力破解、可疑进程与外连、异常账户、近期改动的启动项 |
| ops_change | 文件、新建文件和目录的备份、变更、验证和失败恢复;按组逐台滚动,首台失败即停 |
| ops_exec | 批量命令:并发执行,执行前做风险分级 |
| ops_hosts / ops_history | 能力探测;操作审计、巡检历史与磁盘/内存趋势(审计按月、巡检按条数自动保留) |
| ops_task | 运行例行任务:内置采集器、只读命令或检查脚本,附上一次结果供对比;mode=last 直接读取 WispOps 定时器已保存的结果 |
| ops_template_draft | 提交检查模板草稿,由你在面板审核后保存;不能直接写任务库、关联服务器或启用调度 |
| ops_script_draft | 提交检查脚本草稿,由你在面板测试、审核后保存;脚本任务可由 WispOps 定时器运行,只在异常时才唤醒 agent |

另带 6 个技能:磁盘写满、生信存储清理、安全排查、定时汇报、安全变更、GPU/Slurm。详见 docs/features.md。

支持企业微信、钉钉、飞书和邮件网关 webhook 通知,可只在异常、仅状态变化时投递并设置静默时段;面板随 Harness 切换中英文。设备同步 可通过坚果云 WebDAV 传输加密凭据、任务配置和明确选定的 SSH 私钥。详见通知、变更、同步与更新。

权限

每条命令分为 read / change / sudo / destructive,按 主机策略 > 分组 > 默认 裁决为 allow、ask 或 deny。默认只读直接执行,其余逐次审批;也可以在服务器详情的「操作权限」里按服务器改成 allow / ask / deny,或用 /ops-allow sudo @gpu 2h 临时放行,/ops-revoke all 撤销。模型不能读写清单、数据目录和密码库,包括通过只读命令读取密钥文件。

密码库使用 XChaCha20-Poly1305 加密,密钥存放在 macOS 钥匙串、Windows DPAPI 或权限为 0600 的文件中。详见 docs/security.md。

文档

- 安装与常见问题
- 管理面板与任务库
- 功能、技能与路线图
- 权限模型与密码库
- 配置与 YAML 任务
- 通知、安全变更、设备同步与更新
- 版本记录
- npm 发布配置与发版流程

开发

npm install
npm test
npm run typecheck
npm run build

lib/ 已纳入 Git,GitHub 安装直接使用。修改 src/ 或 client/ 后执行 npm run build,并把 lib/ 一起提交。测试中的 tests/fixtures/fake-ssh.sh 在本机模拟远程命令。

限制

- 目标主机按 GNU/Linux 处理,不支持 Windows 目标。
- 外部通知发送采集摘要;没有 commands 的 custom 任务仍需模型继续采集,不会伪装成已完成报告。
- 调度依赖 Harness 常驻和已打开的报告会话;错过的时间点不自动补跑,面板只标出疑似漏跑(cron 不判断)。
- 安全变更恢复范围限于列出的路径;设备同步是人工触发的快照替换,更新安装后需重启。

License

MIT
预览分享卡片长什么样 ↓wisp-science/WispOps
分享 · DeepSeek Harness Hub
wisp-science/WispOps

WispOps(dsh-wisp-ops):DeepSeek Harness 的多主机服务器运维插件——集群巡检、磁盘与近期文件分析(含组学数据清理建议)、安全排查、按服务器定时生成报告、人工审批的 sudo

这是你的仓库?认领条目

回到顶部