jsdvjx/dshn--packages-agent ↗★ 0
@dshn/agent
通过 ds.hn 将本机的 DeepSeek Harness (dsh) Web 服务转发至公网:包含指向中继的传出 WSS 隧道以及允许转发请求通过的信任围栏集成。
AI 分析
核心用途是实现 DSH 服务的安全公网穿透。适合需要远程访问部署在局域网或本地机器上的 DSH Web 界面的用户。
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:jsdvjx/dshn#e0162faa254386b9bad04fbebf1e91c9b874ee92&path:packages/agent说明文档
阅读完整 README ↗dshn-agent
The dsh plugin half of dshn. It opens one outbound WebSocket
to the relay, claims a subdomain with the (subdomain, password) the user typed in
the setup dialog, and replays whatever the relay forwards against the local dsh
web server — HTTP over node:http, dsh's own /api/events.* downlink sockets
over a tunnelled ws client.
Two halves:
- Host (
src/index.ts→lib/index.js): the tunnel client, the replay engine, the reconnect/heartbeat loop, credential persistence, and the/dshn/status·/dshn/configure·/dshn/disconnectroutes. - Browser (
client.js, hand-authored factory format): ashell.overlaypill that opens the setup dialog when unconfigured (subdomain + password), or the live status + public URL when connected.
Why no trustedHosts patch
The agent rewrites each forwarded request's Host/Origin to the local loopback
authority before replaying it to dsh. dsh's /api browser-trust fence then
accepts it as a loopback, same-origin request — for any subdomain, with no
composition-time trusted-host entry. That is what lets the subdomain be chosen at
runtime in the dialog; access is gated by the relay's login instead of the fence.
Config
Credentials (subdomain + password) are not configured here — the user sets
them in the dialog (POST /dshn/configure, loopback-only) and they persist to
DSHN_STATE. Only infrastructure is env-configured:
| env | meaning | default |
|---|---|---|
DSHN_RELAY_HOST | host the tunnel dials | relay.ds.hn |
DSHN_ORIGIN_CA | PEM cert to pin when dialing a direct grey-cloud origin | — |
DSHN_STATE | file the chosen credentials persist to | ~/.dshn-agent.json |
DSHN_LOCAL_PORT | local dsh port to replay against | the web server's port |
DSHN_ENABLED | 0 loads the plugin inert | 1 |