DSH plugin 凭据怎么接:CredentialRef、按操作解析与 CredentialInfo

配置与使用发布于 2026-10-17作者: DeepSeek Plugin 插件市场
DeepSeek HarnessDSH pluginCredentialRef凭据脱敏seam
DSH plugin 凭据 seam 的接法:配置里只放 CredentialRef 引用、消费方每次操作重新解析、describe 只给可写性不给值,以及 set/unset 与 modifyRecord 两条写路径。

DSH plugin 的凭据 seam 只有一条底线:配置里永远只放引用,不放值。 settings 分节与 cordis.yml 条目携带的都是 CredentialRef(环境变量名),真正的密钥由 dsh-credentials-local 这类提供方持有;消费方每次操作都重新解析,因此轮换后的凭据不需要重启就能作用于下一次请求。这条设计还带出一个硬规则:空的存储值在任何地方都视为不存在——resolve 会跳过它,describe 会报未配置,避免「空字符串冒充已配置的密钥」。

理解这两点,剩下的读、写、描述三类接口就都顺了。

DSH plugin 凭据 seam 的底线:配置只放引用

一句话结论:引用可以出现在配置里,值只属于提供方——这是凭据能安全备份、分享与跨设备同步的前提。

  1. 配置里写引用:settings 里存的是环境变量名,cordis.yml 条目同样只写引用。
  2. 值归提供方:本地提供方从进程环境、提供方管理的存储与 .env 文件三层取到值。
  3. 空值即不存在:seam 级规则,空白存储值不会被当成已配置。
  4. 落盘检查:提交前确认配置里没有任何形似密钥的长字符串。
  5. 验证:把配置分享给另一台机器,引用仍在、值需要在新机器上单独配置——这才是正确的状态。

DSH plugin 的两种键空间:引用与记录

一句话结论:引用回答「这个环境变量后面是什么」,记录回答「这个插件为某 id 持有什么凭据」——后者不可分层、存在即事实。

键空间回答的问题是否分层主要操作
CredentialRef环境变量名后面是什么是(环境 / 存储 / .env)resolve、describe、set、unset
CredentialKey插件为某 id 持有什么否readRecord、describeRecord、listRecords、modifyRecord、deleteRecord
  1. 引用用于密钥类场景:模型 API key、第三方服务 token。
  2. 记录用于授权类场景:OAuth 授予一类的插件自有凭据。
  3. 引用没有枚举接口:配置界面从 settings schema 学到有哪些引用;记录则必须能枚举,否则界面既列不出已授权项,也找不到卸载插件留下的孤儿记录。
  4. 别混用:把记录当引用去 resolve,拿不到任何东西。

DSH plugin 按操作解析:为什么不要缓存 resolve

一句话结论:每次操作重新 resolve,是热更新的实现方式;缓存等于把轮换挡在门外。

  1. 调用形态:
ts
const resolved = await ctx.credentials.resolve(ref)
if (!resolved) { /* 未配置:给出明确提示,而不是拿空串去请求 */ }
// resolved.value 与 resolved.source
  1. LLM 适配器就是范例:每次模型请求解析一次,所以轮换后下一次请求立即生效。
  2. 不要跨操作缓存:官方明确要求消费方不得缓存,按操作读取本身就是机制。
  3. 未配置返回 undefined:用 undefined 分支处理,不要用空串兜底。
  4. 验证:改掉环境变量值,不重启,直接发下一次请求,应使用新值。

DSH plugin 的 describe、CredentialInfo 与可写性

一句话结论:describe 只给事实不给值;writable: false 表示有只读来源遮蔽,写了也是白写。

ts
interface CredentialInfo {
  configured: boolean
  source?: string
  writable: boolean
}
  1. 界面用它渲染徽标:是否已配置、来自哪一层、能不能写。
  2. 本地提供方的只读情形:由当前进程环境供值的引用被报告为 writable: false——写入会表面成功,但解析持续返回遮蔽值,所以 seam 直接拒绝。
  3. 界面提前置灰:看到 writable: false 就渲染成只读,而不是让用户点了才报错。
  4. 变更通知:credentials/reference-updated 在 set、unset 或观察到外部编辑后发出,用于刷新徽标;进程环境自身的变化不可观测,不会发事件。
  5. 消费方不需要这个事件:按操作重新解析就够了,事件只服务配置界面。

DSH plugin 的写入:set/unset 与 modifyRecord

一句话结论:引用用 set/unset,记录只用 modifyRecord——后者是唯一能安全刷新 token 的路径。

  1. 引用写入:
ts
await ctx.credentials.set(ref, value)   // 空值会被拒,删除请用 unset
await ctx.credentials.unset(ref)        // 删不存在的引用是 no-op
  1. 只读遮蔽时会被拒:set 与 unset 在只读来源遮蔽时都拒绝,避免假成功。
  2. 记录写入:
ts
await ctx.credentials.modifyRecord(key, async (current) => {
  // current 是独占时刻的记录;返回 undefined 表示不改
  return next
})
  1. 为什么不能先读再写:两个进程同时刷新同一 refresh token 时,后写会覆盖先写;modifyRecord 在一次持锁的读—改—写里完成,跨进程也成立。
  2. 授权流程另有入口:ctx.authorization 注册取凭据的流程,同一 key 同时只允许一次尝试,重复注册会以 DUPLICATE_FLOW 拒绝。

DSH plugin 排查注意事项

一句话结论:凭据问题先分「读不到」「写不进」「界面看不到」三类,再判断是层级遮蔽还是流程冲突。

  1. 读不到 → 看 resolve 是否返回 undefined,确认环境变量名与提供方层级。
  2. 写不进 → 看 describe().writable 是否为 false(只读遮蔽)。
  3. 界面看不到 → 引用没有枚举接口,检查 settings schema 是否声明了它。
  4. 轮换不生效 → 检查是否在插件里缓存了 resolve 结果。
  5. token 刷新丢写 → 改成 modifyRecord,不要先读再写。
  6. 修复状态如实:本文的引用/记录两种键空间、空值规则、按操作解析与写入拒绝语义均取自官方「用户凭据」页面与包源码注释;接口签名以该页 Cordis API 区块与你所用版本为准。

来源:用户凭据、dsh-credentials 源码、插件配置表单。

常见问题

DSH plugin 的配置里能不能直接写 API 密钥?官方推荐怎么放?

DSH plugin 的配置里只应该放凭据引用(环境变量名),不要写密钥本身。settings 分节与 cordis.yml 条目携带的都是 CredentialRef,真正的值由凭据提供方持有,这样配置可以安全分享与备份。

DSH plugin 里,为什么解析出来的凭据不能在插件里缓存起来复用?

DSH plugin 的凭据解析是按操作进行的,缓存会破坏热更新:值被轮换后你不会重新解析,仍用旧值请求。官方要求消费方每次操作都重新 resolve,轮换后的凭据无需重启就能作用于下一次请求。

DSH plugin 里,describe 返回的 writable 为 false 是什么意思,还要继续写吗?

DSH plugin 的 describe 返回 writable 为 false,说明当前有只读来源遮蔽该引用,例如进程环境变量供值。此时写入会表面成功而解析仍返回遮蔽值,所以 seam 直接拒绝,界面应把它渲染成只读。

DSH plugin 里,CredentialRef 和 CredentialKey 有什么区别?

DSH plugin 的凭据有两个键空间:CredentialRef 是环境变量名,可分层解析;CredentialKey 是插件持有的某条凭据记录,没有可读环境,记录存在即事实。前者用于密钥类引用,后者用于授权记录。

DSH plugin 里,更新 token 时为什么必须用 modifyRecord,而不能先读再写?

DSH plugin 的 modifyRecord 是一次串行的读—改—写,全程持锁,跨进程也生效。先读再写会让两个进程同时刷新同一 token 时丢掉后写方,所以记录的唯一写路径就是 modifyRecord。

相关术语

CredentialRef(凭据引用)
CredentialRef 是指向一条凭据的具名引用,形式为 POSIX 风格环境变量名,构造时按 shell 标识符语法校验。它让配置只携带引用而不携带值。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/credentials
CredentialInfo(凭据描述)
CredentialInfo 是给配置界面用的凭据事实:是否已配置、由哪一层供值、当前是否可写,结构里没有任何能承载值的槽位。正因如此它才能安全地跨 Remote 传输。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/credentials
CredentialKey(凭据记录键)
CredentialKey 标识插件为某个 id 持有的一条凭据记录,例如授权授予。与引用不同,它没有可解析的环境层,记录是否存在就是全部事实。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/credentials
modifyRecord
modifyRecord 是凭据记录唯一的写路径,对单条记录做串行的读—改—写并在支持的后端上跨进程持锁。它让 token 刷新这类读决定写的操作不会互相覆盖。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/credentials

来源