概述
deepseek-harness 是预构建的 DeepSeek Harness Web UI 运行环境。它在隔离的 Sandbox
中启动 dsh web,通过浏览器访问 Harness 的会话、任务和工具界面,适合需要把 Harness
作为临时开发工作区交给开发者或自动化流程的场景。
模板基于 agents-base,内置 Node.js、Python、Git 和常用排障工具;不内置任何
DeepSeek API key。每个 Sandbox 创建时注入自己的 API key 和 Web UI 登录密码,避免
不同 Sandbox 之间共享凭据。
长期架构、认证边界和版本演进策略见模板方案。
模板内容
| 组件 | 说明 |
|---|---|
@deepseek-ai/dsh |
固定版本 0.1.2-alpha.5 的 DeepSeek Harness CLI |
| Harness Web UI | 运行在 Sandbox 内 127.0.0.1:3080 |
| Web 网关 | 运行在 0.0.0.0:8080,负责登录和 HTTP / SSE / WebSocket 转发 |
| Supervisor | 使用启动命令继承的运行时 ENV,并负责重启 dsh 和网关 |
| 公共工具 | Node.js 24.x、Python、git、ripgrep、vim、GitHub CLI、pnpm、tsx、vite |
Harness 保持 loopback 监听,公网只暴露网关端口 8080。创建 Sandbox 后使用
sandbox.getHost(8080) 获取访问地址。
创建 Sandbox
创建时至少提供 DEEPSEEK_API_KEY 和 DSH_WEB_PASSWORD。密码应由调用方随机生成并
保存在自己的安全存储中,不要写入 URL、日志或前端代码。浏览器流量需要到达模板内的
网关,因此示例开启 allowPublicTraffic;envd 继续使用 secure 模式保护运行时 API。
SDK 连接七牛 Sandbox 控制面时需要 QINIU_API_KEY 和 QINIU_SANDBOX_API_URL;兼容
E2B SDK 命名的 E2B_API_KEY 和 E2B_API_URL 也可以使用。
import { setTimeout as delay } from "node:timers/promises";
import { Sandbox } from "e2b";
function requiredEnv(name, ...aliases) {
for (const key of [name, ...aliases]) {
if (process.env[key]) return process.env[key];
}
throw new Error(`${[name, ...aliases].join(" or ")} is required`);
}
const apiKey = requiredEnv("QINIU_API_KEY", "E2B_API_KEY");
const apiUrl = requiredEnv("QINIU_SANDBOX_API_URL", "E2B_API_URL");
const deepseekApiKey = requiredEnv("DEEPSEEK_API_KEY");
const webPassword = requiredEnv("DSH_WEB_PASSWORD");
const sandbox = await Sandbox.create("deepseek-harness", {
apiKey,
apiUrl,
timeoutMs: 60 * 60 * 1000,
secure: true,
network: { allowPublicTraffic: true },
envs: {
DEEPSEEK_API_KEY: deepseekApiKey,
DEEPSEEK_BASE_URL: "https://api.deepseek.com",
DSH_HOME: "/home/user/.dsh",
DSH_WEB_USER: "sandbox",
DSH_WEB_PASSWORD: webPassword,
},
});
await sandbox.commands.run("/opt/deepseek-harness/start.sh");
const webURL = `https://${sandbox.getHost(8080)}`;
let ready = false;
for (let attempt = 0; attempt < 30; attempt++) {
try {
const response = await fetch(`${webURL}/_health`, {
signal: AbortSignal.timeout(3000),
});
if (response.ok) {
ready = true;
break;
}
} catch (error) {
if (attempt === 29) throw error;
}
await delay(1000);
}
if (!ready) throw new Error("gateway is not ready");
// webPassword 应通过调用方的安全存储或授权渠道提供,不要写入日志。
console.log({ webURL, webUser: "sandbox" });
创建完成后执行的 start.sh 通过 SDK 已认证的 envd 命令接口启动运行时进程。示例会等待
/_health 返回 200 后再提示访问。该命令继承
创建请求中的 envs,因此 API key 和登录密码不需要经过公开端口再次传递。
getHost(8080) 返回主机名,示例为其补充 https:// 协议后得到浏览器地址。不要把平台的
e2b-traffic-access-token 当作浏览器登录凭据;浏览器入口由模板网关的登录页保护。
浏览器登录
打开 webURL 后输入创建 Sandbox 时使用的 DSH_WEB_USER 和 DSH_WEB_PASSWORD:
- 未登录访问返回登录页。
- 登录成功后网关设置 8 小时有效的 HttpOnly、Secure、SameSite Strict Cookie,并跳转到 Harness。
- UI 的普通请求、SSE 请求和 WebSocket 连接都会复用该 Cookie。
- 登录失败响应会延迟 500 毫秒,正确凭据不会被其他请求锁定。
/_health 是内部就绪检查端点,不需要登录;它只有在 Harness 后端可达时返回 200。
环境变量
| 变量 | 必需 | 默认值 | 说明 |
|---|---|---|---|
DEEPSEEK_API_KEY |
是 | 无 | DeepSeek 模型 API 凭据 |
DEEPSEEK_BASE_URL |
否 | 上游默认值 | 模型 API 地址 |
DEEPSEEK_SEARCH_BASE_URL |
否 | 上游默认值 | 搜索服务地址 |
DSH_HOME |
否 | /home/user/.dsh |
Harness 配置、profile 和会话目录 |
DSH_WEB_USER |
否 | sandbox |
Web UI 登录用户名 |
DSH_WEB_PASSWORD |
是 | 无 | Web UI 登录密码,UTF-8 编码至少 16 字节,建议每个 Sandbox 随机生成 |
模板构建阶段没有用户的 envs。构建快照中网关会使用一次性随机密码完成启动;创建
Sandbox 后,通过 SDK 调用 start.sh,让 supervisor、dsh 和网关继承 envd 为该命令
提供的运行时 ENV。正式 Sandbox 必须注入自己的 DSH_WEB_PASSWORD 并执行启动命令,
否则调用方没有已知的登录凭据。
生命周期
启动 Sandbox 时,SDK 执行 start.sh,以运行时 ENV 重新拉起 dsh web 和网关;
supervisor 会在任一子进程异常退出后重启二者。Harness 配置和工作区文件保存在 Sandbox
文件系统中。暂停与恢复不会改变外部 URL 的端口格式或运行时 ENV。
使用完成后删除 Sandbox,及时使 URL、会话 Cookie 和运行时 API key 失效:
await sandbox.kill();
故障排查
可以通过 SDK 执行以下命令查看监听状态和日志:
console.log((await sandbox.commands.run(
"ss -lntp | grep -E ':3080|:8080'",
)).stdout);
console.log((await sandbox.commands.run(
"tail -n 80 /tmp/deepseek-harness/dsh.log /tmp/deepseek-harness/gateway.log",
)).stdout);
/_health非 200:先检查 3080 是否监听,再查看 dsh 日志和DEEPSEEK_API_KEY。- 登录失败:确认已通过 SDK 执行
start.sh,且创建请求中的密码满足最小长度要求。 - UI 请求断开:确认访问的是
getHost(8080),并检查平台 Proxy 是否允许长连接。
参考
- DeepSeek Harness:https://github.com/deepseek-ai/deepseek-harness
- 模板构建和发布:使用 qshell 管理沙箱模板
- 完整模板和运行示例:Qiniu Cookbook - DeepSeek Harness