前言¶
在公司或团队里,常见做法是把一台 DeepSeek Harness(DSH)部署成单实例 Web 服务,让多人通过浏览器共用。模型调用往往要对接公司网关或各家云厂商,凭据通常写在服务器环境变量或 Harness 配置里——结果是额度、计费都落在同一套 Key 上,个人很难「用自己的账户、自己的额度」。
下面介绍社区插件 dsh-multiuser-keys(包名 @local/dsh-multiuser-keys,维护者 az13js,分类 admin-security)。它让管理员指定「哪些 provider 需要用户自备 Key」,用户在浏览器里填写并保存;Key 只留在用户本机,随请求进入服务器内存参与解析,不落盘。未列入映射的 provider 仍走 Harness 默认凭据,便于以后改为公司统一发额度。
这是什么¶
dsh-multiuser-keys 面向「同一台 Harness 被多人共用」的场景:每人用自己的 provider API Key,消耗各自账户额度。
插件以当前 DSH 进程权限运行;安装前请自行阅读源码与仓库中的许可证信息。社区目录为独立站点,与 DeepSeek / 幻方无官方从属关系。
工作原理(摘要)¶
- 浏览器:Key 保存在
localStorage;同源/api请求携带 headerx-dsh-user-keys(内容为 base64url 编码的 JSON),不发给第三方域名。 - 服务器 Host 半(
index.js):在 HTTP 层读取 header,用AsyncLocalStorage记录本次请求的 Key 环;包装ctx.credentials.resolve(),仅拦截管理员配置的凭据引用(apiKeyEnv名),其余委托原生实现。 - 服务器 Client 半(
client.js):在「设置 → 我的 API Key」提供配置页。 - 内存与生命周期:Key 在服务器上仅存于进程内存(会话绑定最多 512 条 + 最近活动 Key 环,默认 30 分钟内有效)。重启或更新后,用户浏览器下次请求会自动带上 Key,无需额外操作。
核心功能¶
- 管理员配置哪些 provider(如
llm-pi-ai路由名)需要用户自备 Key;未配置的 provider 行为与未装插件时一致。 - 用户侧设置页显示已映射 provider 的「已配置 / 未配置」,Key 输入默认掩码;保存后对下一次请求生效,清除则回退服务器默认凭据。
- 不新增 HTTP 端点,复用既有
/api;与--trusted-host、Nginxproxy_pass透传请求头的用法兼容(注意勿在网关日志中记录含 Key 的请求头)。 - 可选配置:
recentRingWindowMs、header、source、logResolutions等(见管理员配置一节)。
安装与启用¶
前置:目标机器上有 pnpm(Harness 插件管理器需要;仅有 corepack 时可 corepack enable pnpm,或使用 exec corepack pnpm "$@" 的 shim)。
把插件目录放到服务器任意位置(例如 /opt/dsh-plugins/dsh-multiuser-keys),然后二选一:
方式一(推荐):在 GUI 插件页安装,或由 Agent 调用 plugin_manager install_bundle,target 传目录绝对路径。
方式二:命令行等价操作:
dsh plugin --profile web add /opt/dsh-plugins/dsh-multiuser-keys
并把 "@local/dsh-multiuser-keys" 追加到 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 数组。
也可将包发布到公司私有 registry 后按包名安装。README 说明本插件无安装脚本、无 npm 依赖,安装不会触发 build script。
Kubernetes:$DSH_HOME(默认 ~/.dsh)下 profiles/web/ 须在镜像构建阶段装好插件,避免 Pod 重建后插件丢失。示例片段:
COPY dsh-multiuser-keys /opt/dsh-plugins/dsh-multiuser-keys
RUN dsh plugin --profile web add /opt/dsh-plugins/dsh-multiuser-keys \
&& node -e "const f='/root/.dsh/profiles/web/package.json',fs=require('fs'),p=require(f);p.dsh.profile.bundles.includes('@local/dsh-multiuser-keys')||p.dsh.profile.bundles.push('@local/dsh-multiuser-keys');fs.writeFileSync(f,JSON.stringify(p,null,2))"
管理员配置¶
任选一种方式。
A. 写在 profile patch 的插件行(完整示例见仓库 config.example.yml):
- id: multiuser-keys
name: "@local/dsh-multiuser-keys"
config:
providers:
- provider: company-gateway
label: 公司大模型网关
# - provider: openrouter
# ref: OPENROUTER_API_KEY
B. 独立 JSON 文件(适合 ConfigMap 挂载):
- id: multiuser-keys
name: "@local/dsh-multiuser-keys"
config:
configFile: /etc/dsh/multiuser-keys.json
{ "providers": [ { "provider": "company-gateway", "label": "公司大模型网关" } ] }
ref 可省略:插件会从 settings 读取该 provider 的 apiKeyEnv;读不到的 provider 会告警并跳过。改完配置需刷新浏览器页面,provider 目录随首页 HTML 下发。
典型用法(用户)¶
- 打开 Harness Web:设置 → 我的 API Key(英文界面为 My API keys)。
- 对每个已映射的 provider 粘贴自己的 Key → 保存。
- 发一条对话或任务,确认走个人 Key 的计费路径(需在管理员侧完成 provider 映射并刷新页面)。
自检(Host 侧):
node test/host.test.mjs
卸载:插件管理器 remove_bundle @local/dsh-multiuser-keys;浏览器中的 Key 清站点数据即可。
适用场景与注意¶
适合:单实例容器或内网 Harness,多人 Web 共用,且希望部分模型路由由各人自带 Key、其余仍用服务器统一凭据。
已知限制(摘自 README):
- 同一会话被两人同时用时,会话绑定以最后一次请求为准,无用户级会话隔离——建议各自独立会话。
- 桌面端 IPC、ACP/CLI 等非 Web 通道无法注入浏览器 Key,行为等同未配置。
- 无会话上下文的后台任务在
recentRingWindowMs内可能使用「最近活跃用户」的 Key,超出则回退默认凭据。 - Models 设置页仍反映服务器端凭据状态;用户 Key 状态以本插件设置页为准。
- Key 信任边界与同源页面相同:能在该站点执行脚本的主体可读取
localStorage。
README 记载在本机 Harness(0.2.0-rc.2,web profile)上做过安装与 Host 测试;真实浏览器下的保存、header 往返及映射后的计费路径,需在你的环境中自行点验。
结尾¶
dsh-multiuser-keys 用「浏览器存 Key + 请求头注入 + 服务端按映射解析凭据」的方式,在不大改 Harness 部署形态的前提下,把部分 provider 的额度拆到个人。若你正在维护多人共用的 DSH,可从目录页与 GitHub 仓库查看说明与 config.example.yml,再按上述步骤安装与配置。
- 目录页:https://www.skillhub.cn/plugins/az13js/dsh-multiuser-keys
- GitHub:https://github.com/az13js/dsh-multiuser-keys