Vision & Multimodal

dsh-relay-isolation

AlannerFranklin/dsh-relay-isolation · ★ 0

AlannerFranklin

Provision a separate DSH_HOME for a model relay, so relay traffic never shares your main Harness sessions or credentials.

README body is shown in Chinese.

License
MIT
Added
2026-10-30
Maintenance
active
Install kind
npm
npm
dsh-relay-isolation
Manifest details
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-10-30T09:38:27.365Z
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add 'dsh-relay-isolation@0.4.1'

从 npm 安装预构建包

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: zh · Read Chinese README

Table of contents
  1. English
  2. Why a separate home, not just a separate profile
  3. Install
  4. Use
  5. What it generates
  6. Network inside the sandbox
  7. Permissions it gets
  8. Relay-side limits
  9. Limits
  10. 中文
  11. 为什么必须是独立 home,而不是独立 profile
  12. 安装
  13. 使用
  14. 沙箱里的网络
  15. 权限模型
  16. 中转站侧的限制
  17. 边界

English | 中文


English

0.4.0 — provider-agnostic. The plugin no longer hardcodes AgentRouter, a protocol, or a model list. You pass provider (api / baseURL / apiKeyEnv / models); api: "auto" probes /v1/responses and then /v1/chat/completions and records what actually works. preset: "agentrouter" stays available for that relay's endpoint switch and User-Agent fence. The host-side network tool moved to the standalone dsh-sandbox-net package, and a generated environment installs it automatically.

A DeepSeek Harness bundle that provisions a separate DSH_HOME for a third-party model relay or any OpenAI-compatible endpoint, so relay traffic never runs inside your main Harness profile.

Why a separate home, not just a separate profile

A profile only separates plugin composition. Sessions, storages, and .credentials.yaml live in DSH_HOME and are shared by every profile that uses the same home — so a relay profile in ~/.dsh still lists your main conversations and can read every key you stored. This plugin creates a sibling home instead:

~/.dsh            main Harness: official models, your keys, your sessions
~/.dsh-relay      relay home: one profile, one key, its own sessions

The isolated home holds only AGENTROUTER_API_KEY; other credentials are never copied.

Install

dsh plugin --profile <your-profile> add dsh-relay-isolation

Use

The bundle registers one agent tool, relay_isolation:

action what it does
status reports whether the isolated home exists, whether its profile is configured, whether the relay route is installed, whether a key is present
setup creates or refreshes it; idempotent
remove deletes it, including the sessions stored there; requires force: true

Ask your agent: "create an isolated relay environment" — it calls relay_isolation with action: "setup". On Windows a double-click launcher is written to the Desktop; elsewhere ~/.dsh-relay/launch.sh is written and made executable.

The launcher installs dsh-llm-agentrouter into the isolated profile on first start, then boots dsh with --port 0 and opens its own UI.

What it generates

~/.dsh-relay/
  .credentials.yaml            only AGENTROUTER_API_KEY
  launch.cmd | launch.sh
  profiles/relay/
    package.json               bundles: dsh-base, dsh-web-app, dsh-llm-agentrouter
    cordis.yml
    cordis.patch.yml           default model + relay route with silent retry
    pnpm-workspace.yaml

The relay route and its request compatibility (client User-Agent, direct transport for the domestic endpoint, tool-schema repair) come from dsh-llm-agentrouter. This plugin configures it; it does not reimplement it.

Network inside the sandbox

The Windows sandbox hands shell commands a token without network capability, so curl inside the isolated environment cannot reach anything. Raising the mode to danger-full-access would fix that by removing the sandbox — the wrong trade.

Instead the bundle registers a second tool, relay_fetch, which performs the request in the host process (unsandboxed) against an explicit allowlist:

Host Why
registry.npmjs.org package metadata and tarballs
api.github.com, github.com, raw.githubusercontent.com repository discovery and file reads
cdn.jsdelivr.net, 社区精选目录, dshmarket.com plugin catalog

GET only, HTTPS only, 60 KB per call by default, 20 s timeout. The write boundary is unchanged: the sandbox still confines the agent to its workspace.

Configuration:

- id: relay-isolation
  name: dsh-relay-isolation
  config:
    allowedHosts: ['registry.npmjs.org']   # replaces the default list

Permissions it gets

The isolated environment is provisioned to be useful inside its box and unable to reach outside it:

Capability Default Detail
Workspace read/write yes The launcher cds into <home>/workspace; the sandbox pins workspaceRoot to that directory
Command execution yes Sandboxed; approval ask fails closed when nobody answers
Outbound npm / GitHub yes Needed to install the relay route; model traffic already goes to the relay
Credentials only AGENTROUTER_API_KEY Other keys in the main home are never copied

What it does not guarantee: DSH's workspace-write bounds writes, not reads. An agent inside the isolated environment can still read paths outside its workspace. For a real boundary, run the launcher as a separate OS user or in a VM.

Relay-side limits

The Responses API is stateful: a follow-up request may reference an item created by the previous one. A relay that spreads requests across several upstream resources breaks that, and the upstream answers "The requested item was created under a different Azure OpenAI resource". No profile setting fixes this — the relay has to pin a conversation to one upstream. Note also that supportsStore is a completions-only switch: openai-responses rejects it and accepts supportsDeveloperRole, supportsMaxOutputTokens, supportsStrictMode, supportsLongCacheRetention.

Limits

  • It cannot isolate the running host: DSH_HOME is fixed when a process starts. Isolation applies to the environment it provisions.
  • The generated profile is relay; the generated home is $(dirname $DSH_HOME)/.dsh-<suffix>.
  • Installing the relay package needs network access on first launch.
  • remove deletes that home, including its sessions. It refuses to run without force: true, and refuses to delete DSH_HOME itself.

中文

一个 DeepSeek Harness bundle,给第三方模型中转站(AgentRouter)单独开一个 DSH_HOME,让中转站流量不进入主 Harness profile。

为什么必须是独立 home,而不是独立 profile

profile 只隔离插件组合。会话、存储、.credentials.yaml 都在 DSH_HOME 里,同一个 home 下的所有 profile 共用——所以 ~/.dsh 里再建一个 relay profile, 它照样列出你的主会话,也读得到你存的每个密钥。本插件建的是兄弟目录:

~/.dsh            主 Harness:官方模型、你的密钥、你的会话
~/.dsh-relay      中转站环境:一个 profile、一个密钥、自己的会话

隔离环境里只有 AGENTROUTER_API_KEY,其他凭据一律不复制。

安装

dsh plugin --profile <你的 profile> add dsh-relay-isolation

使用

装好后会注册一个 agent 工具 relay_isolation:

action 作用
status 报告隔离环境是否存在、profile 是否已配置、中转站路由是否装好、有没有密钥
setup 创建或刷新(幂等)
remove 删除,连同里面的会话;必须带 force: true

直接对 agent 说「建一个中转站隔离环境」即可;Windows 上会在桌面写一个双击启动器, 其他平台写到 ~/.dsh-relay/launch.sh 并加可执行位。

启动器首次运行会把 dsh-llm-agentrouter 装进隔离 profile,然后用 --port 0 起一个自己的界面。

沙箱里的网络

Windows 沙箱交给命令的是无网络能力的令牌,所以隔离环境里 curl 连不出去。把模式提到 danger-full-access 能解决,但那是拿掉沙箱——方向反了。

本 bundle 注册第二个工具 relay_fetch:请求在宿主进程里发出(不受沙箱限制),目标 主机走白名单(npm registry、GitHub、插件目录),GET only、HTTPS only、默认 60 KB、 20 秒超时。写入边界不变——沙箱仍然把 agent 锁在它的工作区里。

- id: relay-isolation
  name: dsh-relay-isolation
  config:
    allowedHosts: ['registry.npmjs.org']   # 替换默认列表

权限模型

隔离环境是「盒子内够用、盒子外够不着」:

能力 默认 说明
工作目录读写 ✅ 启动器会 cd 到 <home>/workspace,沙箱的 workspaceRoot 就是它
命令执行 ✅ 沙箱内执行;审批 ask,无人应答时 fail closed
出网 npm / GitHub ✅ 装中转站路由需要;模型流量本来就走中转站
凭据 只有 AGENTROUTER_API_KEY 主 home 里的其他 key 一律不复制

它不保证的事:DSH 的 workspace-write 限制的是写,不是读。隔离环境里的 agent 仍然可能读到工作区之外的路径。要拿到真正的边界,请用独立的操作系统账户或 虚拟机运行这个启动器。

中转站侧的限制

Responses API 是有状态的:后续请求可能引用上一跳创建的 item。如果中转站把请求分散到多个 上游资源上,这一点就会被打破,上游会回 "The requested item was created under a different Azure OpenAI resource"。这不是配置能修的——得让中转站把同一段对话固定到同一个上游。 另外 supportsStore 是 completions 专有开关,openai-responses 不接受,它只接受 supportsDeveloperRole、supportsMaxOutputTokens、supportsStrictMode、 supportsLongCacheRetention。

边界

  • 它无法隔离正在运行的宿主:DSH_HOME 在进程启动时固定,隔离对新建的环境生效;
  • 中转站路由与请求兼容(User-Agent、国内端点直连、工具 schema 修补)来自 dsh-llm-agentrouter,本插件只做配置;
  • 首次启动需要联网安装该路由包;
  • remove 会删掉整个 home(含会话),无 force: true 时拒绝执行,也拒绝删 DSH_HOME。

MIT