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

网页远控 liangkw16/dsh-web-control

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

用手机或电脑浏览器接管正在运行的 DSH 会话

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

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

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

状态速览

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

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 45 处,展示前 40 条)
  • 发起网络请求
    packages/plugin/src/host-operations.ts:56
    this.bridge = new InteractionBridge(incoming, this.fence, authenticatedEvents(this.ctx), id => this.scope.assertSession(id), sharedEventReply(request
  • 发起网络请求
    packages/plugin/src/host-transport.ts:64
    const response = await fetch(new URL('/v1/devices/register', this.test?.origin ?? identity.relayOrigin), {
  • 发起网络请求
    packages/plugin/src/index.ts:43
    async fetch(request) {
  • 读取本地文件
    packages/plugin/src/index.ts:67
    const profileScope = createHash('sha256').update(await realpath(ctx.profileContext.dir)).digest('hex')
  • 发起网络请求
    packages/plugin/src/management.ts:21
    ctx.connection.fetch.register({ path: '/api/web-control/manage', methods: ['POST'], requestBody: 'buffered', async fetch(request) {
  • 写入本地文件
    packages/relay/build.mjs:2
    await mkdir(new URL('./dist/migrations/', import.meta.url), { recursive: true })
  • 写入本地文件
    packages/relay/build.mjs:3
    await copyFile(
  • 写入本地文件
    packages/relay/src/backup.ts:10
    await mkdir(dirname(path), { recursive: true })
  • 写入本地文件
    packages/relay/src/backup.ts:11
    try { await mkdir(path, { mode: 0o700 }) } catch { throw new Error('Database occupied; stop relay before this operation (stale locks require manual ve
  • 删除本地文件递归
    packages/relay/src/backup.ts:12
    return async () => { await rm(path, { recursive: true }) }
  • 读取本地文件
    packages/relay/src/backup.ts:15
    async function exists(path: string): Promise<boolean> { try { await lstat(path); return true } catch (e) { if ((e as NodeJS.ErrnoException).code === '
  • 读取本地文件
    packages/relay/src/backup.ts:16
    async function regularFile(path: string): Promise<void> { if (!(await lstat(path)).isFile()) throw new Error('Database must be a regular file, not a s
  • 写入本地文件
    packages/relay/src/backup.ts:33
    await db.backup(temporary); await chmod(temporary, 0o600); await sync(temporary)
  • 删除本地文件
    packages/relay/src/backup.ts:36
    } finally { await rm(temporary, { force: true }) }
  • 删除本地文件
    packages/relay/src/backup.ts:65
    await rm(databasePath + '-wal', { force: true }); await rm(databasePath + '-shm', { force: true })
  • 写入本地文件
    packages/relay/src/backup.ts:66
    await rename(temporary, databasePath); await sync(dirname(databasePath))
  • 删除本地文件
    packages/relay/src/backup.ts:68
    try { target?.close() } finally { await rm(temporary, { force: true }); await release() }
  • 读取本地文件
    packages/relay/src/cli.ts:16
    const secret = path === '-' ? await new Promise<string>((resolve, reject) => { let text = ''; process.stdin.setEncoding('utf8'); process.stdin.on('dat
  • 写入本地文件
    packages/relay/src/cli.ts:49
    await writeFile(path, randomBytes(32).toString('base64url') + '\n', { mode: 0o600, flag: 'wx' }); print('Enrollment secret initialized in private file
  • 写入本地文件
    packages/relay/src/cli.ts:73
    const temporary = path + '.rotate'; await writeFile(temporary, randomBytes(32).toString('base64url') + '\n', { mode: 0o600, flag: 'wx' })
  • 写入本地文件
    packages/relay/src/cli.ts:74
    try { await rename(temporary, path) } finally { await rm(temporary, { force: true }) }; print('Enrollment rotated; force-recreate the relay container
  • 删除本地文件
    packages/relay/src/cli.ts:74
    try { await rename(temporary, path) } finally { await rm(temporary, { force: true }) }; print('Enrollment rotated; force-recreate the relay container
  • 读取本地文件
    packages/relay/src/db.ts:24
    db.exec(readFileSync(new URL('./migrations/001.sql', import.meta.url), 'utf8'))
  • 读取本地文件
    packages/relay/src/server.ts:266
    const root = await realpath(config.staticDir),
  • 读取本地文件
    packages/relay/src/server.ts:267
    file = await realpath(
  • 读取本地文件
    packages/relay/src/server.ts:272
    const info = await stat(file)
  • 读取本地文件
    packages/relay/src/server.ts:294
    const stream = createReadStream(file)
  • 读取本地文件
    packages/relay/src/static-readiness.ts:12
    const root = await realpath(directory)
  • 读取本地文件
    packages/relay/src/static-readiness.ts:13
    const entry = await realpath(resolve(root, 'index.html'))
  • 读取本地文件
    packages/relay/src/static-readiness.ts:15
    const info = await stat(entry)
  • 读取本地文件
    packages/relay/src/static-readiness.ts:19
    const html = await readFile(entry, 'utf8')
  • 读取本地文件
    packages/relay/src/static-readiness.ts:26
    const file = await realpath(resolve(root, path))
  • 读取本地文件
    packages/relay/src/static-readiness.ts:27
    if (relative(root, file).startsWith('..') || !(await stat(file)).isFile()) throw new Error()
  • 读取本地文件
    packages/relay/src/ui-assets.ts:18
    const entry=join(root,'index.html'),info=await lstat(entry)
  • 读取本地文件
    packages/relay/src/ui-assets.ts:20
    if(/name=["']dsh-ui-release["']/.test(await readFile(entry,'utf8')))return invalid()
  • 读取本地文件
    packages/relay/src/ui-assets.ts:35
    file=join(file,part);const info=await lstat(file)
  • 读取本地文件
    packages/relay/src/ui-assets.ts:41
    const path=await regular(release.root,asset.path),info=await lstat(path)
  • 读取本地文件
    packages/relay/src/ui-assets.ts:43
    const bytes=await readFile(path);if(bytes.length!==asset.bytes||hash(bytes)!==asset.sha256)return invalid();return bytes
  • 读取本地文件
    packages/relay/src/ui-assets.ts:48
    if((await lstat(directory)).isSymbolicLink())return invalid()
  • 发起网络请求
    packages/web/src/connect.ts:18
    const response = await this.fetch(`/v1/instances/${instanceId}/login`, { method: 'POST', credentials: 'same-origin', redirect: 'error', headers: { 'Co
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh-agent@deepseek-ai/dsh-api-gateway@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-api-workspace-files@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-attachment@deepseek-ai/dsh-brand@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-file-upload@deepseek-ai/dsh-client-locale
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 浏览器接管运行中会话
  • 桌面与手机双端控制
  • 自托管中继

用 DSH 自带 Web UI 和自托管中继,在桌面和手机浏览器里控制运行中的 DeepSeek Harness 会话。

README

由 DeepSeek 最新模型翻译生成
DSH Web Control English · 安装 · 部署 Relay · 版本与限制 · Releases 通过链接或二维码,在电脑、平板和手机浏览器中接管正在运行的 DeepSeek Harness 会话。 尽可能复用 DSH 原版 Web UI,Web Control 只负责认证、连接与有限能力桥接。 无需开放电脑的入站端口,无需远程桌面。 这是独立社区插件,与 DeepSeek 没有隶属或官方背书关系。当前版本 v0.1.0,验证目标为 DSH 0.2.0-rc.2;其他 DSH 版本未声明兼容。Relay 需自行部署,本项目不提供公共托管服务。 能做什么 - 原版会话列表、消息、执行进度、工具记录、队列操作和审批交互。 - 在电脑与移动浏览器间切换,新页面可接替旧控制页面。 - 原版文件卡片、历史 diff、侧栏标签和完整文件预览;支持浏览器下载与上传。 - 插件在 DSH Host 中保持连接,关闭设置页面或仅锁屏后仍可使用;休眠、断网和退出 DSH 会影响连接。 - 通过版本协商和明确的命令接口适配,保留 DSH 原版业务资源,避免维护另一套聊天界面。
展开完整文档(README 剩余 1 节)
DSH Web Control

English · 安装 · 部署 Relay · 版本与限制 · Releases

通过链接或二维码,在电脑、平板和手机浏览器中接管正在运行的 DeepSeek Harness 会话。

尽可能复用 DSH 原版 Web UI,Web Control 只负责认证、连接与有限能力桥接。 无需开放电脑的入站端口,无需远程桌面。

这是独立社区插件,与 DeepSeek 没有隶属或官方背书关系。当前版本 v0.1.0,验证目标为 DSH 0.2.0-rc.2;其他 DSH 版本未声明兼容。Relay 需自行部署,本项目不提供公共托管服务。

能做什么

- 原版会话列表、消息、执行进度、工具记录、队列操作和审批交互。
- 在电脑与移动浏览器间切换,新页面可接替旧控制页面。
- 原版文件卡片、历史 diff、侧栏标签和完整文件预览;支持浏览器下载与上传。
- 插件在 DSH Host 中保持连接,关闭设置页面或仅锁屏后仍可使用;休眠、断网和退出 DSH 会影响连接。
- 通过版本协商和明确的命令接口适配,保留 DSH 原版业务资源,避免维护另一套聊天界面。

工作方式

flowchart LR
Browser[PC / 移动浏览器] <-->|HTTPS / WSS| Relay[自托管 Relay]
Host[DSH Host + 插件] <-->|主动建立 WSS| Relay
Host --> Session[原版会话与工作区服务]

Relay 负责认证、路由和静态 UI 分发。浏览器与 Host 均通过 TLS 连接到 Relay,不是端到端加密:部署者必须信任自己的 Relay。控制链接是访问凭据,不要公开分享。

快速开始

1. 从 v0.1.0 Release 下载插件 dsh-web-control-0.1.0.tgz、部署包及 SHA256SUMS,按部署指南启动 HTTPS Relay。
2. 在 DSH 桌面 App 的「插件 → 添加插件」中安装下载的 .tgz,启用插件。CLI 用户可运行:

npx @deepseek-ai/dsh@0.2.0-rc.2 plugin --profile web add ./dsh-web-control-0.1.0.tgz

3. 首次使用时,由 Relay 管理者生成一次私有连接配置,在 DSH「设置 → 网页远控」导入;日常使用只需打开生成的链接或扫码。
4. 保持 DSH 运行,在另一台设备的浏览器打开链接即可。停止远控、刷新链接与接管规则见安装指南。

预构建 tarball 不需要在安装时执行构建脚本。源码仓库是 monorepo;不要把仓库根目录当成可直接安装的插件包。

文档

| 文档 | 内容 |
| 安装与配对 | 桌面 / CLI、首次配置、控制链接、升级卸载 |
| Relay 部署 | Docker Compose、HTTPS、IP:port、备份回退 |
| 架构 | 原版 UI 复用、状态同步和权限边界 |
| 兼容性 | 支持范围、文件限制、浏览器验收边界 |
| 排障 | 连接、证书、文件读取与锁屏 |
| 贡献指南 | 构建、测试、PR 要求 |
| 发布流程 | 制品、校验、验证与官方发现入口 |
| 安全政策 | 威胁模型、漏洞报告、凭据保护 |

本地开发

需要 Node.js 24.x、pnpm 11.25.0。运行测试只使用隔离 fixture,不连接你的生产 DSH。

corepack enable
corepack prepare pnpm@11.25.0 --activate
pnpm install --frozen-lockfile
pnpm build
pnpm typecheck
pnpm test

Relay 镜像还需要固定的原版 UI 资源;不能只运行 docker build。使用完整部署包,或按发布流程组装 release-input/web。

许可证与来源

本项目使用 MIT。DeepSeek Harness 和其他依赖保留各自许可证,见 THIRD_PARTY_NOTICES.md。原版 UI 资源的许可证随部署包分发。

DeepSeek 官网的“社区插件”指向 GitHub dsh-plugin topic,这是本项目采用的官方发现路径;不是“官方审核通过”的标志。
预览分享卡片长什么样 ↓liangkw16/dsh-web-control
分享 · DeepSeek Harness Hub
liangkw16/dsh-web-control

用手机或电脑浏览器接管正在运行的 DSH 会话

这是你的仓库?认领条目

回到顶部