dsh-workspace-api-key
A DeepSeek Harness plugin that binds a separate DeepSeek API key to each workspace, or to a single session, so the spend of one key stays with the sessions you choose.
這個插件適合誰
- 經常開長會話、需要會話管理的人
安装
dsh plugin --profile web add dsh-workspace-api-key
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| T0 静态检查 | — |
| T1 安装 | ✓ |
| T2 列装 | ✓ |
| T3 挂载 | ✓ |
| T4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-workspace-api-key
[English](README.md) | 中文
一个 DeepSeek Harness 插件:为每个工作区——必要时也可以为单个会话——单独绑定一把 DeepSeek API key。
DSH 只从一个全局凭据 ref(默认 DEEPSEEK_API_KEY)解析 DeepSeek key,于是所有工作区的所有会话花的都是同一把 key。这个插件加了一个面板,让单个工作区、甚至单个会话可以用自己的 key,这样一把 key 的花费就只落在你指定的会话上。没有单独配置的层级继续用上层设置:
会话 key → 工作区 key → 系统默认
你会得到
- 一行侧栏入口,叫「API Key 分配」,紧跟在宿主自己的「插件」行下方,点开是全宽页面。
- 按工作区配置的 key —— 列出
workspaceRegistry服务里注册的全部工作区,各自一个 key 输入框。 - 按会话配置的 key —— 每个工作区行可以展开(默认折叠),列出该目录下的会话,每个会话有自己的 key;从上层继承的会话会如实标注层级,而不是假装自己配了 key。
- 系统默认卡片 —— 当前生效的 ref、值的来源(
file、env等)以及打码后的值。 - 测试连接 —— 用该 key 真发一次
POST <baseURL>/messages(max_tokens: 1),返回ok、invalid、quota、rate-limit或unreachable;测试成功会顺手清掉失效标记。 - key 失效提醒 —— 401/403 把绑定的 key 标为
invalid,402 标为quota,429 标为rate-limit。当你点进一个生效 key 已失效的会话时,覆盖层会说明情况,并给出去配置、改用上层设置或稍后。 - 不匹配提醒 —— 如果绑 key 时记下的是某个服务商(比如
deepseek-official),而该会话现在跑在另一个服务商上,点进这个会话时会提醒你,因为那次请求会拿着对方不认的 key 发出去。 - 绝不悄悄换 key —— 两种提醒都不会改动实际使用的 key,决定权始终在你手上;自动替换会直接破坏「按会话分离计费」这个初衷。
- 一键回退 —— 清空会话条目回到工作区 key,清空工作区条目回到系统默认。
- 搜索默认 key 单独一把 —— 「搜索默认 key」卡片把这把 key 绑到
DEEPSEEK_API_KEY_SEARCH,于是搜索可以和聊天分开计费:会话自己的 key 最优先,其次勾了同步的工作区走聊天层级,再次是这把搜索默认 key,最后才是官方搜索页里配的那把。 - 接管官方搜索 key 设置(先有 key 才接管) —— 启动时若已启用新版 Web 搜索 API,插件把官方
web-deepseek-api/web-search-deepseek条目的apiKeyEnv指到DEEPSEEK_API_KEY_SEARCH(只改这一个指向,永远不动 key 内容)。此后「设置 → 插件 → 网页搜索」里填的就是本面板这把搜索 key,既不会再顶掉聊天 key,也不存在第二处藏搜索 key 的地方。还没配搜索 key 时,官方条目继续指着聊天那把,所以升级不会让web_search直接失效,面板会如实提醒「搜索暂时和聊天共用一把 key」。 - 每个工作区一个搜索开关 —— 每个工作区行上都有「同步搜索 API」复选框。勾选后,该目录下会话发出的
web_search/web_fetch请求改用它们聊天时用的那把 key(会话 → 工作区 → 系统默认);不勾选则继续用官方「设置 → 插件 → 网页搜索」里配置的那把 key。会话自己配了 key 时永远优先,所以「工作区同步、会话单独设置」花的是会话那把 key,而不是搜索默认 key。 - 在失败之前就提醒的搜索告警 —— 配了搜索 key 但没打开「启用新版 Web 搜索 API」,或者新版 API 打开了但它的 key ref 是空的,面板会显示提醒条,点进会话时的覆盖层也会用一句可直接照做的话说明;当生效的搜索通道不是新版 API 时,覆盖层不会拿搜索问题打扰你。
- 使用说明 —— 面板顶部有「使用说明」,推荐两把 key 分工:聊天默认用
default,搜索默认用search-default,两份预算互不干扰;里面还画了层级,并列出了会触发提醒的几种情况。
实现方式
宿主半边(lib/index.js):
- 每个进程包装一次
credentials.resolve(通过ctx.effect在卸载时还原),而不是去注册第二个同名服务或第二条 provider 路由——对一个已被占用的名字,cordis 不允许这两者; - 从
agents.currentInitiator()?.session取当前会话的目录与 id:agent loop 把整个回合跑在那个异步作用域里,所以解析凭据时这两个值都拿得到,解析器据此选中「有 key 的最具体层级」; - 把该目录与
workspaceRegistry.list()做规范化后比对(绝对化、去掉尾部分隔符、Windows 折大小写); - 由每一层派生出稳定的 ref —— 工作区是
DEEPSEEK_API_KEY_WS_<sha1(规范化路径) 前 16 位十六进制大写>,会话是DEEPSEEK_API_KEY_SS_<sha1(会话 id) 前 16 位十六进制大写>(会话 id 含-,不能直接当 ref 名)——通过凭据服务写入 key,并返回这个 ref 的值; - 只改写 provider 真正会读的 ref:默认 ref、每个适配器配置的
apiKeyEnv,以及插件自己生成的 ref;其它 ref 原样透传; - 把「搜索请求」和「聊天请求」分开——按 ref 分辨,而不是包住 web 服务。官方新版 Search/Fetch API 自己解析 key,用的是
web-deepseek-api.apiKeyEnv指向的凭据;本插件在启动时(以及面板每次保存搜索 key 时)把它指到插件自有的DEEPSEEK_API_KEY_SEARCH,于是只看 ref 就能认出「这是搜索在要 key」:聊天永远不会解析这个 ref。0.2.15 起删掉了原先「把ctx.web.search/ctx.web.fetch包进AsyncLocalStorage」的做法——包住 web 服务可能让web_search/web_fetch一直挂到工具 30/60 秒预算耗尽(连http://127.0.0.1:1/这种必然立刻失败的地址也一样挂)。规则本身没变:先看会话自己的 key(永远最优先),再看该工作区有没有勾「同步搜索 API」,勾了就依次用工作区 key、系统默认 key;没勾时先用插件面板自己持有的搜索默认 ref(若配了),最后才用搜索插件配置的那个 ref。旧版基于 Messages 的搜索仍然走原来的聊天层级,因为那条路线本身就是一次 messages 请求; - 会话列表来自
sessionController服务(list(),会拆开它{items: […]}的信封),控件缺失 / 抛错 / 列表为空时再退到宿主 live 会话服务(ctx.get('sessions').list()),所以那种情况下面板仍能列出会话;侧栏藏起来的两种会话这里也藏:子代理会话(origin: 'subagent'或带parentSession)和空会话(建了但一句话都没发过,侧栏只显示当前开着的那个)。两种都不过滤的话,一个只有 1 个真实会话的工作区会列出 13 个; - 不是注册工作区的目录,只有侧栏真的会显示它才会被列出来。这件事宿主判不了:「空会话里只有当前开着的那个算数」是浏览器端才知道的事(
retainedBy.mainView),所以宿主把这种目录连同每个会话的blank标记一起发出去,并用hiddenBlankDirs点名「里面全是空会话」的目录,由浏览器半边套用与侧栏一致的判据; /wsk-api/state会带上插件自身版本与会话探针(available、shape、source、count、withoutCwd、subagents、samples、error,以及工作区路径样本),面板据此说明为什么没有列出会话:宿主半边是旧版本(只刷新了页面而没重启应用)、没有sessionController、list()抛错、信封形状不认识,还是会话的cwd与任何工作区路径都对不上;- 自己的账本(哪一层对应哪个 ref、失效标记、key 是给哪个服务商记的)落在
$DSH_HOME/storages/dsh-workspace-api-key.json; - 通过
agent/request-errorwaterfall 观察失败,但从不返回{kind: 'retry'}——只记录判定结果并next()放行。
浏览器半边(lib/client.js)注册到 sidebar.panellist 槽(order: 1)、main 槽(key 为 workspace-api-key)与 shell.overlay 槽(点进会话时的提醒),和 dsh-skill-mcp-panel、dsh-429-guard 用的是同一套槽。全部是朴素的 React.createElement,没有构建步骤,也不打包任何依赖。它会把宿主行与浏览器端 sessions 存储(ctx.get('sessions').list.getSnapshot(),也就是侧栏自己渲染的数据)合并起来,因此标题取自 displayTitle,浏览器端只认识一部分会话时也不会把宿主行挤掉,宿主列不出会话时面板也照样有会话可列。这个存储由 dsh-api-session-controller 在插件 apply() 之后才提供,所以面板与覆盖层都会为它重试(每 500ms 一次,最多 40 次),而不是首次渲染拿不到就放弃。覆盖层向 /wsk-api/check?sessionId=…&path=… 查询当前占据主视图的会话,每个会话最多问一次,它的按钮只负责把你带到面板——改 key 只能由面板里的操作完成。
HTTP 接口(仅限回环)
方法 · 路径 · 用途
GET · /wsk-api/state · 默认 ref 状态、工作区及其会话、覆盖项、失效标记
GET · /wsk-api/resolve · 当前会话此刻解析到哪一层、哪个 ref
GET · /wsk-api/check · ?sessionId=…&path=… 只读判定:生效层级、key、失效标记、服务商不匹配、needsAttention
POST · /wsk-api/set(搜索) · {scope: 'search-default', key} 绑定面板自己的搜索默认 key;{useDefault: true} 清除
POST · /wsk-api/set · {scope: 'workspace' \ · 'session', path \ · sessionId, title, key, provider?} 绑定 key;{useDefault: true} 或空 key 为清除
POST · /wsk-api/test · {scope, path \ · sessionId \ · ref}(或 {key})真发一次请求并返回判定;invalid 打标记,ok 清标记
POST · /wsk-api/clear-flag · {ref} 或一个目标,清掉失效/配额标记
POST · /wsk-api/search-sync · {path, enabled} —— 打开或关闭某个工作区的「同步搜索 API」
只接受本机回环调用(127.0.0.1、::1、::ffff:127.0.0.1),且 Origin 必须同源或缺失。任何响应都不会包含明文 key,只有掩码。
工作区目标也接受不是注册工作区的目录;这类条目会作为「未分组目录」列在面板里,且只列侧栏真的会显示的目录——一个目录里若只有「刚建好、一句话都没发过」的空会话,侧栏不会显示它(空会话里只有当前打开的那个算数),面板也不会列。
安装
插件被市场收录后,可以直接在「设置 → 插件市场」里一键安装;也可以从 npm 装:
# 用 DSH 自带的 CLI 装进某个 profile(web、tui……)。Desktop 自己的 profile # 由 Electron 应用独占管理,请在它的界面里安装。 dsh plugin --profile web add dsh-workspace-api-key
这条命令会把参数原样转交给 profile 目录里的 pnpm,等价的手写形式是:
# 在 profile 目录里,例如 ~/.dsh/profiles/web pnpm add dsh-workspace-api-key # 或者:npm install dsh-workspace-api-key
锁版本用 `dsh-worksp
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
嵌入徽章
两个徽章各用自己站的标识:左边是**标准**(DSHIO 发布),右边是**检测机构**(deepseekbase 检测)。每次展示都指向标准原文和检验报告。
Markdown(推荐,两个一起)
[](https://dshio.org/10/) [](https://deepseekbase.com/zh/plugins/dsh-workspace-api-key/)
注意:这不是认证。DSHIO/T 32 认证规则尚未启用。
版本
npm 上共发布:18,最后更新 2026-11-04
链接
常見問題
dsh plugin --profile web add dsh-workspace-api-key。如果你用的是 DSH Desktop,也可以在插件頁面直接貼套件名。dsh --version),再看上面測試結果區的第一條錯誤。還不行就到 GitHub 倉庫提 issue。dsh plugin --profile web remove dsh-workspace-api-key。