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

常驻沙箱 zhming0/dsh-yawn

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

常驻网页版 DeepSeek Harness,每个会话一个沙箱。🥱

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

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

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add zhming0/dsh-yawn
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · security
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-yawn-workspace(未发布到 npm,仅可源码安装)
✓Node 引擎要求 ^22.19.0 || >=24 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 20:00:33

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 61 处,展示前 60 条)
  • 读取本地文件
    control-plane/image/profile-refresh.mjs:24
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    control-plane/image/profile-refresh.mjs:38
    carriedPath !== undefined && existsSync(carriedPath) ? readJson(carriedPath) : {};
  • 写入本地文件
    control-plane/image/profile-refresh.mjs:69
    writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}\n`);
  • 写入本地文件
    control-plane/src/broker.ts:57
    await mkdir(dirname(this.options.path), { recursive: true, mode: 0o700 });
  • 读取本地文件
    control-plane/src/broker.ts:66
    JSON.parse(await readFile(this.options.path, "utf8")),
  • 写入本地文件
    control-plane/src/broker.ts:236
    await writeFile(temporary, snapshot, { mode: 0o600 });
  • 写入本地文件
    control-plane/src/broker.ts:237
    await chmod(temporary, 0o600);
  • 写入本地文件
    control-plane/src/broker.ts:238
    await rename(temporary, this.options.path);
  • 写入本地文件
    control-plane/src/checkpoint.ts:362
    await mkdir(this.directory, { recursive: true, mode: 0o700 });
  • 删除本地文件
    control-plane/src/checkpoint.ts:371
    await rm(this.artifactsPath(sessionId), { force: true });
  • 删除本地文件
    control-plane/src/checkpoint.ts:386
    rm(this.bundlePath(sessionId), { force: true }),
  • 删除本地文件
    control-plane/src/checkpoint.ts:387
    rm(this.artifactsPath(sessionId), { force: true }),
  • 读取本地文件
    control-plane/src/checkpoint.ts:393
    return await readFile(path);
  • 写入本地文件
    control-plane/src/checkpoint.ts:404
    await writeFile(temporary, bytes, { mode: 0o600 });
  • 写入本地文件
    control-plane/src/checkpoint.ts:405
    await rename(temporary, path);
  • 读取本地文件
    control-plane/src/deployment-settings.ts:30
    raw = readFileSync(path, "utf8");
  • 读取本地文件
    control-plane/src/deployment-settings.ts:66
    raw = readFileSync(importedPath, "utf8");
  • 写入本地文件
    control-plane/src/file-index.ts:61
    await mkdir(this.directory, { recursive: true, mode: 0o700 });
  • 写入本地文件
    control-plane/src/file-index.ts:65
    await writeFile(temporary, JSON.stringify(file), { mode: 0o600 });
  • 写入本地文件
    control-plane/src/file-index.ts:66
    await rename(temporary, path);
  • 读取本地文件
    control-plane/src/file-index.ts:72
    text = await readFile(this.pathFor(sessionId), "utf8");
  • 删除本地文件
    control-plane/src/file-index.ts:87
    await rm(this.pathFor(sessionId), { force: true });
  • 发起网络请求
    control-plane/src/file-reference.ts:264
    const task = this.fetch(agent).then(
  • 发起网络请求
    control-plane/src/file-reference.ts:302
    private async fetch(agent: Agent): Promise<FileIndex | undefined> {
  • 读取本地文件
    control-plane/src/fs.ts:47
    readFile(hostPath, signal === undefined ? {} : { signal }),
  • 写入本地文件
    control-plane/src/instruction-store.ts:20
    await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
  • 读取本地文件
    control-plane/src/instruction-store.ts:23
    JSON.parse(await readFile(this.path, "utf8")),
  • 写入本地文件
    control-plane/src/instruction-store.ts:64
    await writeFile(temporary, snapshot, { mode: 0o600 });
  • 写入本地文件
    control-plane/src/instruction-store.ts:65
    await chmod(temporary, 0o600);
  • 写入本地文件
    control-plane/src/instruction-store.ts:66
    await rename(temporary, this.path);
  • 发起网络请求
    control-plane/src/mcp-oauth.ts:393
    return fetch(url, {
  • 写入本地文件
    control-plane/src/mcp-store.ts:132
    await mkdir(dirname(this.options.path), { recursive: true, mode: 0o700 });
  • 读取本地文件
    control-plane/src/mcp-store.ts:141
    JSON.parse(await readFile(this.options.path, "utf8")),
  • 写入本地文件
    control-plane/src/mcp-store.ts:334
    await writeFile(temporary, snapshot, { mode: 0o600 });
  • 写入本地文件
    control-plane/src/mcp-store.ts:335
    await chmod(temporary, 0o600);
  • 写入本地文件
    control-plane/src/mcp-store.ts:336
    await rename(temporary, this.options.path);
  • 读取本地文件
    control-plane/src/registration-token.ts:14
    const existing = readFileSync(path, "utf8").trim();
  • 写入本地文件
    control-plane/src/registration-token.ts:23
    mkdirSync(stateDir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    control-plane/src/registration-token.ts:25
    writeFileSync(path, `${token}\n`, { mode: 0o600 });
  • 读取本地文件
    control-plane/src/runner-image.ts:9
    readFileSync(new URL("../package.json", import.meta.url), "utf8"),
  • 写入本地文件
    control-plane/src/scratch-workspace.ts:57
    await mkdir(path, { recursive: true, mode: 0o700 });
  • 读取本地文件
    control-plane/src/skills.ts:72
    const content = readFileSync(path, "utf8");
  • 写入本地文件
    control-plane/src/state-store.ts:36
    await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
  • 读取本地文件
    control-plane/src/state-store.ts:38
    const parsed = JSON.parse(await readFile(this.path, "utf8")) as unknown;
  • 写入本地文件
    control-plane/src/state-store.ts:97
    await writeFile(temporary, snapshot, { mode: 0o600 });
  • 写入本地文件
    control-plane/src/state-store.ts:98
    await chmod(temporary, 0o600);
  • 写入本地文件
    control-plane/src/state-store.ts:99
    await rename(temporary, this.path);
  • 启用终端会话(PTY)
    control-plane/src/subprocess.ts:124
    return this.terminals.spawn(
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:41
    await mkdir(root, { recursive: true, mode: 0o700 });
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:42
    await chmod(root, 0o700);
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:43
    await mkdir(path, { recursive: true, mode: 0o700 });
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:44
    await chmod(path, 0o700);
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:57
    await writeFile(temporary, `${JSON.stringify(metadata, null, 2)}\n`, {
  • 写入本地文件
    control-plane/src/workspace-anchor.ts:60
    await rename(temporary, metadataPath);
  • 删除本地文件
    control-plane/src/workspace-anchor.ts:62
    await rm(temporary, { force: true });
  • 读取本地文件
    control-plane/src/workspace-anchor.ts:71
    return { path: await realpath(path), repositoryUrl, title };
  • 读取本地文件
    control-plane/src/workspace-anchor.ts:83
    realpath(anchorRoot(stateDir)),
  • 读取本地文件
    control-plane/src/workspace-anchor.ts:84
    realpath(cwd),
  • 读取本地文件
    control-plane/src/workspace-anchor.ts:111
    const expected = await realpath(
  • 读取本地文件
    control-plane/src/workspace-anchor.ts:303
    const value = JSON.parse(await readFile(path, "utf8")) as unknown;
扫描于 2026/10/31(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 常驻网页运行
  • 每会话独立沙箱

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness Yawn 常驻在 Web 上的 DeepSeek Harness。 自托管发行版:部署一次,从任意浏览器打开,每个会话都跑在自己的沙箱里。 为什么做这个 DeepSeek Harness 是个很棒的 harness,但它假定自己跑在你的笔记本上:每个会话共用你的操作系统,所以你得盯着智能体在干什么,得让机器一直醒着,还得忍受一台机器的规模。DSH Yawn 把 dsh 拆成两半:harness 本身跑在一台你长期开着的服务器上,智能体做的每件事都跑在自己的沙箱里。名字就是这么来的:你可以躺平打个哈欠 :) | | 笔记本上的 dsh | DSH Yawn | | dsh 本身(Web UI、会话、模型调用) | 你的笔记本 | 一台常驻服务器:虚拟机或 Kubernetes 集群 | | 智能体的工作(shell 命令、文件编辑) | 你的笔记本 | 每个会话一个沙箱:Docker 容器、Kubernetes pod 或 Buildkite 构建 | | 你从哪里打开 | 那台笔记本 | 任意浏览器,登录之后 | | 同时跑多个会话 | 共用一个操作系统、CPU 和磁盘 | 各有一个沙箱,落在你的虚拟机、集群或 Buildkite 代理上 |
展开完整文档(README 剩余 1 节)
DeepSeek Harness Yawn

常驻在 Web 上的 DeepSeek Harness。
自托管发行版:部署一次,从任意浏览器打开,每个会话都跑在自己的沙箱里。

为什么做这个

DeepSeek Harness 是个很棒的 harness,但它假定自己跑在你的笔记本上:每个会话共用你的操作系统,所以你得盯着智能体在干什么,得让机器一直醒着,还得忍受一台机器的规模。DSH Yawn 把 dsh 拆成两半:harness 本身跑在一台你长期开着的服务器上,智能体做的每件事都跑在自己的沙箱里。名字就是这么来的:你可以躺平打个哈欠 :)

| | 笔记本上的 dsh | DSH Yawn |
| dsh 本身(Web UI、会话、模型调用) | 你的笔记本 | 一台常驻服务器:虚拟机或 Kubernetes 集群 |
| 智能体的工作(shell 命令、文件编辑) | 你的笔记本 | 每个会话一个沙箱:Docker 容器、Kubernetes pod 或 Buildkite 构建 |
| 你从哪里打开 | 那台笔记本 | 任意浏览器,登录之后 |
| 同时跑多个会话 | 共用一个操作系统、CPU 和磁盘 | 各有一个沙箱,落在你的虚拟机、集群或 Buildkite 代理上 |
| 从仓库开始 | 你本地的检出目录 | 粘贴 URL;沙箱克隆它并运行 .agents/setup |
| 密钥 | 你的 shell 环境 | 服务器上的存储,执行命令前推送到沙箱 |

发行版里有什么

- 控制平面和 runner 镜像,一起发布、一起测试,外加一个 Helm chart。
- dsh 的 Web UI,它的文件、shell 和搜索工具都跑在会话的沙箱里。
- 沙箱后端:Docker、带预热池的 Kubernetes agent-sandbox,以及 Buildkite。
- 登录方式:内置口令,或在 Helm chart 里配置的身份服务商 OIDC。
- 沙箱配置档和空闲计时器、密钥、AGENTS.md 指令、通知、MCP 服务器和插件的 Web UI 页面,改动后无需重启即可生效。
- 每个会话都有:一个 Sandbox 标签页、一个文件浏览器和一个终端。
- 预览:沙箱里的开发服务器会获得自己的 URL。

环境要求

- 控制平面需要一台常开的机器:一台装了 Docker 的 VM,或者一个 Kubernetes 集群,通过 Helm chart 部署。
- 能把它暴露在一个域名下,公网或局域网都行。
- 需要一处运行沙箱的地方:同一台 VM 上的 Docker、带 agent-sandbox 的 Kubernetes 集群,或者一个 Buildkite 组织。
- Web UI 的登录方式:一个通行码,或者用你的身份服务商做 OIDC。
- 一个模型 API key,在 Web UI 里添加。
- 可选:一个 GITHUB_TOKEN,或其他 Git 主机的凭据,用于私有仓库和推送。

安装步骤:docs/installations.md。

快速开始

下面这条命令在 Docker 里跑控制平面,并把每个会话的沙箱作为兄弟容器启动:整套安装都在一台机器上。同样的形态在 VM 上也能用。

export DSH_YAWN_PASSCODE="$(openssl rand -base64 18)"
printf 'passcode: %s\n' "$DSH_YAWN_PASSCODE"

docker run -d --name dsh-yawn \
-p 127.0.0.1:3000:3000 -p 8081:8081 \
-e DSH_YAWN_BIND_ALL=1 \
-e DSH_YAWN_PASSCODE \
-v dsh-yawn-data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/zhming0/dsh-yawn-control-plane

1. 打开 <http://localhost:3000/>,输入上面打印的通行码。
2. Settings → Sandboxes → New profile:name: standard,backend: docker。
3. 在 Web UI 设置里添加模型凭据。
4. 在 Scratch 工作区发一条消息,它的会话从空沙箱启动;或者用 New session → Add workspace… 填一个仓库 URL。

清理:docker rm -f dsh-yawn。每个参数的作用见 FAQ。

文档

| 页面 | 内容 |
| docs/installations.md | 安装索引:控制平面、runner、凭据 |
| docs/control-plane.md | 控制平面:Kubernetes 上用 Helm chart,或 VM 上用 Docker |
| docs/credentials.md | 密钥存储:GITHUB_TOKEN 和其他 Git 主机、Web UI、控制平面凭据 |
| docs/runners/kubernetes.md | 沙箱作为 Kubernetes pod:安装、安全模型、唤醒后保留什么 |
| docs/runners/buildkite.md | 沙箱作为 Buildkite 构建:流水线、空闲检查点、限制 |
| docs/faq.md | 登录、沙箱生命周期、runner 隧道、插件 |
| control-plane/README.md | 补丁包改了什么、每一项设置、密钥处理 |
| docs/development.md | 仓库结构、构建与测试、checkout 安装、发布 |
预览分享卡片长什么样 ↓zhming0/dsh-yawn
分享 · DeepSeek Harness Hub
zhming0/dsh-yawn

常驻网页版 DeepSeek Harness,每个会话一个沙箱。🥱

回到顶部