Skip to content

dsh-desktop-web-access

Verified

dsh-desktop-web-access · v0.1.0 · MIT · Web UI

DSH desktop plugin: surface and copy the Web GUI launch-token URL (loopback + LAN) so the desktop app's built-in Web server can be opened from another device.

Install

dsh plugin add dsh-desktop-web-access

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Tags

Creators

Readme

dsh-desktop-web-access

一个 DSH 插件:把桌面端 Web 服务的启动令牌找出来,并放到你能复制到的地方。

关于包名:npm 上的 dsh-web-access 已被另一个项目占用(NexusAgentX/dsh-web-access,做的是 ctx.web 搜索/抓取,与本插件无关),所以本包注册为 dsh-desktop-web-access。

要解决的问题

DeepSeek Harness 桌面端启动时会拉起内置 Web 服务(默认 127.0.0.1:19387)。这个服务要求带启动令牌才能打开:

http://127.0.0.1:19387/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

问题在于:dsh-web-app 确实把这行 URL 打印到了标准输出,但桌面端是 GUI 程序、stdout 没有人看得到,日志里也没有。于是令牌拿不到 —— 而后面这个 Web 界面却会返回 401,提示 dsh web authentication required。

令牌每次启动都会重新随机生成,并且只能用来换取一次 cookie(cookie 有效期 30 天,绑定到 host:port,换取成功后浏览器就不再需要令牌了)。

插件做了什么

位置 作用
设置 → Web 访问 完整链接、单独的令牌、局域网/虚拟网卡地址、当前绑定与可达性说明,每项都能单独复制或直接打开
web_access_url 工具 直接问 Agent「给我 Web 访问链接」即可,URL 出现在对话里就能复制
$DSH_HOME/web-access-url.txt 便利文件;插件激活时写入,之后每次读取链接都会刷新

复制按钮把文本放进当前浏览器所在设备的剪贴板里 —— 所以哪怕你是从另一台设备远程连进来的,复制到的也是那台设备的剪贴板,这正是远程场景需要的。

为什么不放侧边栏:侧边栏底部行动区、品牌标记与名称、shell.leading 都是单占用座位,且已被官方 wordmark 与账号菜单占据;在那里常驻一个图标,等于为"每次启动只查一次"的东西付每天的视觉成本。所以链接只放在设置页里,需要时打开即可。

实现要点

  • 令牌本身不落盘(便利文件除外,可用 writeFile: false 关闭)、不进页面:宿主半边通过 ctx.connection.authenticatedUrl() 重新推导出与桌面端完全一致的 URL,再经一条受认证保护的路由提供出去:

    GET /x-dsh-web-access/url   ->   JSON
    
  • 该路由用 ctx.connection.admit() 做与 /api 相同的 Host/Origin 围栏 + 浏览器 cookie 校验,未认证请求只会得到 401,不会看到令牌。插件也不会把令牌注入 index.html。

  • token 字段独立给出,方便只要令牌本身的场景。

安装

从 npm(发布后):

# 在桌面端 profile 目录($DSH_HOME/profiles/desktop)里
pnpm add dsh-desktop-web-access

或者更省事:在桌面端 Web GUI 里让 Agent 用 plugin_manager → install_bundle 装(本地目录、tarball、npm 包名都行)。

本地开发时用 link: 即可,源码改动无需重装:

pnpm add link:/path/to/dsh-desktop-web-access

然后把包名加进 package.json 的 dsh.profile.bundles(plugin_manager 会自动做这一步)。本仓库的 cordis.patch.yml 负责把宿主半边挂到 Loader 上,随包一起安装。

安装后是热生效的,无需重启桌面端。

改宿主半边(src/host.js)后需要重启桌面端:客户端包每次请求都从磁盘重新读取,所以 lib/client.js 的改动刷新页面即可;但宿主半边由 Loader 按模块缓存,实测连 disable/enable 都不会重新执行 —— 想立刻看到宿主改动,重启桌面端最稳。

从另一台设备访问

插件会明确告诉你当前是否可达:

  • 绑定 0.0.0.0(dsh web --bind 0.0.0.0,或桌面端 profile 里配置)→ 直接用「局域网链接」,同一网络的设备打开即可。

  • 只绑定 127.0.0.1(桌面端默认)→ 任何设备都无法通过 IP 直接访问。需要先做端口转发,例如:

    ssh -L 19387:127.0.0.1:19387 <user>@<跑着桌面端的机器>
    

    然后在另一台设备上打开插件给出的那条 127.0.0.1:19387 链接即可(令牌照常有效)。

安全说明

  • 令牌等同于登录凭据:拿到它的任何人只要能连到这个端口,就能拿到 30 天的 cookie。请只发给你信任的设备/通道。
  • 令牌随进程重启变化;旧令牌在新一次启动后立即失效。
  • 插件不写日志、不上传任何东西;唯一写入的文件是 $DSH_HOME/web-access-url.txt(可用配置 writeFile: false 关闭,或用 file 指定路径)。

配置

宿主半边支持三个可选配置项:

- id: dsh-desktop-web-access
  name: dsh-desktop-web-access
  config:
    tool: true          # 注册 web_access_url 工具(默认 true)
    writeFile: true     # 写 $DSH_HOME/web-access-url.txt(默认 true)
    file: ""            # 自定义便利文件路径

配置项之外的说明

  • 插件只依赖 webServer 与 connection 两个服务,不引入任何 npm 依赖。
  • 浏览器半边只 require("react")(平台模块表已提供),无额外 external。

构建

node build.mjs

产出两个文件:

  • lib/client.js —— 浏览器半边(CJS + ModuleLoader 握手;由 Web 宿主作为 dsh-desktop-web-access 这一行提供给浏览器,实际请求形如 /plugins/??dsh-desktop-web-access/client.js&rev=...)
  • lib/index.js —— 宿主半边(由 src/host.js 打包而来)

build.mjs 从 package.json 的 name 推导插件标识,并同时写进 Loader 行名、name 导出与 ModuleLoader bundle id —— 改名时只需改 package.json,三处不会走偏。发布前 prepublishOnly 会自动构建。

License

MIT