DeepSeek Harness 插件

1624318455/dsh-plugin-tavily

Star 数 ★ 5 分类 浏览器与网页 收录于 2026-08-15

基于 Tavily 的网页搜索提供方:替换内置 web_search 的后端,并提供 API Key、结果数量与时间窗口的设置卡片。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:1624318455/dsh-plugin-tavily

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

English | 中文

基于 Tavily 的 web 搜索提供方插件,用于 DeepSeek Harness (dsh)。定位是面向进阶用户的专业版 Tavily 搜索插件:完整暴露 Tavily 请求参数,支持 WebUI 可视化调参与配置文件双模式。

它把 tavily 搜索提供方注册进 harness 的 ctx.web seam,让内置的 web_search 工具通过 Tavily 联网搜索;同时提供一张 设置卡片(设置 → 插件 → 网页搜索),在图形界面里粘贴 API Key、调节高级参数并测试连接。一次安装,两个半部。

功能

  • 即装即用(无需手动配提供方):安装本插件即通过其 cordis.patch.yml 自动把 web_search 提供方选为 Tavily。卡片里粘一个 Key 就能搜,无需改 yaml 或设 DSH_WEB_SEARCH_PROVIDER。
  • Tavily/DeepSeek 引擎开关:GUI 开关让 web_search 由 Tavily(默认;无 Key 走 keyless)应答,或回退到官方 DeepSeek——无需卸载。这是真正切换提供方的开关,不是改配置。
  • 服务端连通探针:POST /api/tavily-probe 让卡片能测试已保存的 Key(浏览器读不回已存密钥),无 Key 时走 keyless。
  • 状态指示器:GET /api/tavily-status 用已保存的 Key 读取 Tavily GET /usage(不消耗搜索额度),卡片常驻显示 ✅ 正常 / ⚠️ 额度不足 / ✗ API 错误(或「未配置 Key」)徽标,由宿主机刷新、无需重新输入密钥。
  • GUI 完整专业参数:API Key、API Base URL、maxResults、searchDepth(basic/advanced/fast/ultra-fast)、topic、includeAnswer、includeRawContent、timeout、days、chunksPerSource、timeRange、startDate/endDate、includeImages、includeDomains/excludeDomains、country 全部可在卡片编辑;高级参数收进默认折叠的 <details> 面板,普通用户不会被大量选项吓到。
  • 参数预设模板:一键暂存一组高级参数——深度研究(advanced 深度、更多结果、返回原始内容)、快速摘要(basic 深度、少量结果、详细摘要)、新闻实时(news 主题、day 时间窗),点「保存」生效;被配置文件覆盖的字段自动跳过。
  • 配置文件优先:cordis.patch.yml > WebUI > 代码默认值。yaml 显式设置的字段在卡片上置灰并显示「该参数已被配置文件覆盖」,WebUI 无法覆盖。
  • API 连通测试:基础设置区提供独立「测试API连接」按钮,直接用当前填写的 key/baseUrl 发起轻量搜索并展示成功/报错信息,报错已分类(Key 无效 / 余额不足 / 限流 / 服务宕机 / 超时 / 网络)并给出对应解决文案。已保存的密钥因安全设计无法被浏览器读回,测试已配置密钥时需要重新输入一次(不会重复保存)。
  • 用量与成本面板:卡片实时显示当前设置的每次搜索积分/token 预估,并提供「检查用量」按钮读取 Tavily GET /usage(剩余额度、搜索用量、套餐)。提供方另有宿主侧 usage() 方法可在已存密钥可用时读取同一数据。
  • 页面抓取:基于 Tavily Extract 的 fetch 提供方(tavily-extract)从 URL 读取整页内容并返回干净的 text/html —— 选择一次后,URL 检索即由 Tavily 应答。
  • 可选 Firecrawl 抓取:另一个 fetch 提供方(firecrawl)通过 Firecrawl POST /scrape(markdown、正文为主)抓取页面,适合 Tavily 提取质量差的页面。它有独立 id 与独立凭据(默认引用 FIRECRAWL_API_KEY);搜索始终走 Tavily,Firecrawl 只负责 URL 检索。未选择时保持惰性。
  • 持久化结果缓存:cacheFile 把 TTL/LRU 搜索缓存持久化到 JSON 文件(重启不丢;支持 ~/,相对路径按工作目录解析)。防抖、尽力而为——磁盘故障绝不阻断搜索。默认关闭。
  • 限流重试与缓存:收到 429 后按 retry-after 做有界退避重试;可选 TTL 缓存让相同查询直接命中以节省额度——缓存带 LRU 上限(默认 200 条),且默认对时效敏感查询(news/finance 主题或任意时间窗口)完全跳过,「现在」类问题绝不命中陈旧快照。
  • 精简调试日志:可选 debug 开关,每次搜索/抓取输出一行可读日志(查询节选、深度、积分、缓存状态、耗时、分类错误)——绝不记录密钥或原始响应体。
  • 多密钥轮换 & 故障转移:apiKeyRefs 列出额外凭据引用(只存引用名,密钥仍在凭据库/环境变量中),与字面量 apiKey、apiKeyEnv 组成轮换环。搜索在 Key 级故障(429 / Key 无效 / 余额不足)时自动切到环中下一把 Key;连续失败 3 次的 Key 进入 60 秒冷却,保证健康 Key 接管。
  • 脚注式引用(证据溯源):citeFormat: footnote 在生成摘要后追加编号来源块(Sources:\n[1] 标题 — url…),模型可按编号引用来源;plain(默认)仅返回摘要原文。
  • 自动兜底引擎:fallbackEngine: deepseek 在 Tavily 出现服务侧故障(超时 / 网络 / 5xx)时改由官方 DeepSeek 搜索应答;Key 级故障(429/401)不触发兜底——那是凭据问题,不是宕机。
  • 凭据优先的密钥解析:每次搜索按 字面量 apiKey → 凭据服务(apiKeyEnv)→ process.env[apiKeyEnv] 的顺序解析。

安装

dsh plugin --profile web add "github:1624318455/dsh-plugin-tavily#main"

开发期间可用本地路径安装:

dsh plugin --profile web add "file:/绝对路径/dsh-plugin-tavily"

插件的 cordis.patch.yml 会把 web.config.searchProvider 设为 tavily,即自动选 Tavily 为提供方(无需手动改配置)。

启用

  1. 安装并重启 dsh。插件已替你设置 web.config.searchProvider: tavily,无需手动选择提供方。

  2. 设置 Tavily API key(可选)。打开 设置 → 插件 → 网页搜索,展开 网页搜索(Tavily) 卡片,把密钥粘贴进 API Key 输入框。没有 Key 时 Tavily 走 keyless(免费、限流),有 Key 走账号档。在 网页搜索引擎 开关里选 Tavily(默认)或 官方 DeepSeek。

  3. 照常使用 web_search。面向模型的工具不变,只是后端换成 Tavily(或你切到的 DeepSeek)。

若日后你想在 yaml 里手动覆盖提供方,对应行是:

# ~/.dsh/profiles/web/cordis.patch.yml
- id: web
  config:
    searchProvider: tavily

启用抓取(Extract)提供方(可选)

插件同时注册一个基于 Tavily Extract 的 fetch 提供方(tavily-extract),用于从 URL 读取整页内容。默认不启用,需像搜索提供方一样选择:

export DSH_WEB_FETCH_PROVIDER=tavily-extract

或在 cordis.patch.yml 中:

- id: web
  config:
    searchProvider: tavily
    fetchProvider: tavily-extract

如需改用可选的 Firecrawl 页面抓取(需要自己的 Key,默认凭据引用 FIRECRAWL_API_KEY):

export DSH_WEB_FETCH_PROVIDER=firecrawl

或把上面同一行的 fetchProvider 改为 firecrawl。未配置 Firecrawl Key 时,抓取会报 WEB_PROVIDER_CREDENTIAL_MISSING,其余时间保持惰性。

验证后端确实是 Tavily

web_search 工具的输出 schema 与提供方无关 —— 模型看不到提供方名称,且 API key 刻意存放在环境变量之外,所以"查环境变量"是错误探测方式。要确认当前后端:

  • 提供方选择 —— ~/.dsh/profiles/web/cordis.patch.yml 中有 web 行且 searchProvider: tavily。
  • 插件已加载 —— ~/.dsh/settings.yaml 含 web-search-tavily 配置节(只有插件的 installSettingsSection 会写入它)。
  • 凭据在位 —— TAVILY_API_KEY 存在于凭据存储(~/.dsh/.credentials.yaml),不在环境变量中。
  • 结果特征 —— Tavily 结果在 content 中携带生成式 answer 摘要;内置 DeepSeek provider 不产生该字段。

故障排查:仍然看到「没有 DeepSeek API key」报错

本插件现已自动选 Tavily(web.searchProvider: tavily),新装即由 Tavily 应答 web_search,正常使用不该再出现此错。若仍看到 DeepSeek key 报错:

  • 你把引擎切到了「官方 DeepSeek」却没配 DeepSeek key。把卡片的「网页搜索引擎」切回 Tavily(或配置 DeepSeek key)。
  • 你在 yaml 里覆盖了提供方。确保没有更靠后的 web patch 行把 searchProvider 指回 deepseek(插件自己的行已选 tavily)。
  • 这是 agent/assistant 环境。聊天应用自己的 web_search 是另一套 web seam、并未安装本插件——它始终用默认 DeepSeek 后端,与你的 Tavily 安装无关。

🖥️ 图形界面使用(推荐普通用户)

打开 设置 → 插件 → 网页搜索,展开 网页搜索(Tavily) 卡片。

  • 基础设置(默认展开):
    • 状态指示器 —— 常驻徽标(✅ 正常 / ⚠️ 额度不足 / ✗ API 错误 / 未配置 Key),由宿主机用已保存的 Key 检查(GET /api/tavily-status 读取 GET /usage,不消耗搜索额度);「刷新」按钮强制重查(自动检查限每分钟一次)。
    • 网页搜索引擎 —— Tavily(默认;无 Key 走 keyless)或 官方 DeepSeek。这是真正的提供方开关;插件已被自动选为提供方。
    • API Key —— 粘贴你的 Tavily 密钥。密钥经凭据服务写入,绝不进入设置文件。
    • API Base URL —— 留空使用 https://api.tavily.com;可填代理/自定义接口地址。
    • 参数预设 —— 一键应用「深度研究 / 快速摘要 / 新闻实时」:多个高级字段被同时暂存(被配置文件覆盖的字段跳过),点「保存」生效。
    • 测试API连接 —— 验证当前输入的 key/baseUrl;失败会分类提示(Key 无效 / 余额不足 / 限流 / 服务宕机 / 超时 / 网络)并附解决建议。测试会消耗一次 Tavily 搜索额度。如果已配置密钥但输入框为空,会提示重新输入一次(浏览器无法读取已保存的密钥)。
    • 预估成本 —— 实时显示当前深度/结果数/片段数对应的预估积分与大致 token 量。
    • 检查用量 —— 用当前输入的 key 读取 Tavily GET /usage,展示剩余额度、搜索用量与套餐;已保存的密钥与测试一样需重新输入一次。
  • 高级搜索参数(🔧 高级 Tavily 请求参数,默认收起):
    • 最大结果数 —— 单次搜索返回网页结果数量(1–20,默认 5)。
    • 搜索深度 —— basic(均衡)、advanced(2 积分,深度)、fast、ultra-fast(1 积分,最低延迟)。
    • 搜索主题 —— general、news 或 finance。
    • 生成摘要答案 —— true/basic(快速)或 advanced(详细)。
    • 返回网页原始内容 —— false、markdown 或 text;开启会大幅增加上下文 token 消耗。
    • 每个来源的片段数 —— 每个来源返回的相关片段数(1–3)。
    • 时间范围 —— 时效预设(day/week/month/year/d/w/m/y)。
    • 开始日期 / 结束日期 —— 精确的 YYYY-MM-DD 发布窗口。
    • 包含图片 / 图片描述 / 包含网站图标 —— 请求更丰富的结果元数据。
    • 包含域名 / 排除域名 —— 站点白/黑名单。
    • 国家加权 —— 偏向某一国家(general 主题)。
    • 限流重试次数 —— 收到 429 后的额外重试次数(0–5);等待遵循 retry-after 并做有界退避。
    • 缓存时长(秒) —— 缓存相同查询以节省额度;0 表示关闭(0–3600)。
    • 缓存条目上限 —— 缓存条目的 LRU 上限(1–10000,默认 200);超出后淘汰最旧条目。
    • 时效性查询跳过缓存 —— 开启(默认)时,news/finance 主题或带时间窗口的搜索完全绕过缓存。
    • 调试日志 —— 每次搜索/抓取输出一行精简日志(查询节选、积分、缓存状态、耗时、错误);绝不记录密钥或原始响应。
    • 引用格式 —— plain(仅摘要,默认)或 footnote(追加 [1] 标题 — url… 编号来源块,模型可按编号引用)。
    • 兜底引擎 —— none(默认)或 DeepSeek(自动兜底):Tavily 服务侧故障(超时/网络/5xx)时改由官方 DeepSeek 应答。
    • 请求超时(毫秒) —— 默认 30000。
    • 时间窗口(天) —— 可选,用于 news/finance 的时效过滤。

每个控件都有简短注释和默认值 placeholder。修改后点 保存 即时生效,无需重启服务。

如果某个字段显示「该参数已被配置文件覆盖,请修改 yaml」,说明它被 cordis.patch.yml 钉住,WebUI 故意不允许覆盖。

⚙️ 配置文件进阶用法(面向开发者)

配置文件即 profile 的 cordis.patch.yml(~/.dsh/profiles/web/cordis.patch.yml)。在 web-search-tavily 行加一个 config 块即可设置任意键:

- id: web-search-tavily
  name: '@dsh-external/dsh-plugin-tavily'
  config:
    searchDepth: advanced
    topic: news
    maxResults: 8
    includeRawContent: false
    timeout: 20000
    engine: tavily
    citeFormat: footnote          # 摘要后追加编号引用块 [1] 标题 — url
    fallbackEngine: deepseek      # Tavily 服务侧宕机时由 DeepSeek 兜底
    apiKeyRefs:                   # 多密钥轮换环(只放凭据引用名)
      - TAVILY_API_KEY_1
      - TAVILY_API_KEY_2

优先级

cordis.patch.yml 配置  >  WebUI 面板保存值  >  代码内置默认值
  • yaml config 中出现的字段,卡片对应控件会置灰并显示配置覆盖提示。
  • yaml 未设置的字段,使用 WebUI 保存的值。
  • 两者都没有时,使用代码内置默认值。

配置键一览

配置键 默认值 含义 GUI 可编辑
apiKey (未设) Tavily API 密钥字面量;建议用凭据服务 密钥输入框(走凭据)
apiKeyEnv TAVILY_API_KEY 凭据引用(环境变量名),每次搜索时解析 仅配置
apiKeyRefs [] 多密钥轮换环的额外凭据引用(仅引用名;密钥在凭据库/env) 仅配置
baseURL https://api.tavily.com 端点基址,追加 /search ✓
maxResults 5 单次搜索默认结果数(1–20) ✓
searchDepth basic basic/advanced/fast/ultra-fast ✓
topic general general、news 或 finance ✓
includeAnswer true 生成式答案:true/basic(快速)或 advanced(详细) ✓
includeRawContent false 原始内容:false、markdown 或 text(耗上下文) ✓
chunksPerSource 3 每个来源的片段数(1–3) ✓
timeRange (未设) 时效预设:day/week/month/year/d/w/m/y ✓
timeout 30000 请求超时(毫秒) ✓
engine tavily 应答 web_search 的引擎:tavily(无 Key 走 keyless)或 deepseek ✓
citeFormat plain 答案/来源排版:plain 或 footnote(编号引用块) ✓
fallbackEngine none Tavily 服务侧故障(超时/网络/5xx)时改为 deepseek 应答 ✓
days (未设) 时效窗口(天),用于 news/finance ✓
retryMaxAttempts 2 收到 429 后的额外重试(0–5) ✓
cacheTtlSeconds 0 查询缓存时长(秒),0 关闭 ✓
cacheMaxEntries 200 缓存条目的 LRU 上限(1–10000) ✓
cacheBypassFresh true 时效敏感查询(news/finance 或带时间窗口)跳过缓存 ✓
cacheFile (未设) 把结果缓存持久化到的 JSON 文件(重启不丢);未设/空则关闭 仅配置
debug false 精简的每次搜索调试日志(绝不记录密钥/原始响应) ✓
firecrawlBaseURL https://api.firecrawl.dev/v1 Firecrawl fetch 提供方接口地址(追加 /scrape) 仅配置
firecrawlApiKey (未设) Firecrawl 字面量 Key;优先用凭据引用 仅配置
firecrawlApiKeyEnv FIRECRAWL_API_KEY Firecrawl 每次抓取解析的凭据引用 仅配置
startDate (未设) 只返回该 YYYY-MM-DD 之后的结果 ✓
endDate (未设) 只返回该 YYYY-MM-DD 之前的结果 ✓
includeImages false 收集查询相关及来源图片 ✓
includeImageDescriptions false 为每张图片附带描述 ✓
includeFavicon false 返回每个结果的 favicon URL ✓
includeDomains [] 只包含这些域名(白名单) ✓
excludeDomains [] 排除这些域名(黑名单) ✓
country (未设) 偏向某一国家(general 主题) ✓
numResults 5 已废弃:maxResults 的旧别名 否(请用 maxResults)

apiKeyEnv 保持「仅配置」:它属于高级接线细节。GUI 保存的值落在 ~/.dsh/settings.yaml 的 web-search-tavily 段。设置改动即时生效 —— 提供方每次操作都会重读配置段,无需重启或重新注册。

平台说明(Web GUI 卡片可见性)

Web GUI 只有在 apiproxy 白名单(@deepseek-ai/dsh-host-apiproxy 的 WEB_SETTINGS_NAMESPACES)内的设置段才会下发给浏览器。截至 0.1.0-rc.6,该列表为硬编码,且"让插件自行暴露其配置"的机制尚未落地,因此第三方插件的卡片即使宿主侧已注册也会被过滤。要让 网页搜索(Tavily) 卡片渲染出来,请在已安装副本的白名单数组中加入该命名空间并重启 dsh:

// ~/.dsh/profiles/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/index.js
// 在 WEB_SETTINGS_NAMESPACES 数组中加入:
"web-search-deepseek",
"web-search-tavily",   // ← 添加这一行

提供方及全部功能无需此补丁即可工作,只是 GUI 卡片被隐藏。pnpm install --force 与 harness 升级都会覆盖此补丁,重装依赖后需重新应用。

用内置脚本应用补丁(幂等;--check 只检测不写入):

node scripts/patch-apiproxy.mjs --check            # 仅报告是否需要补丁
node scripts/patch-apiproxy.mjs                    # 修补所有已安装 profile
node scripts/patch-apiproxy.mjs --profile web      # 只修补指定 profile

已保存密钥的服务端测试:本插件注册了宿主侧探针 POST /api/tavily-probe,可在服务端用已存 Key 测试 Tavily 连通性(无 Key 走 keyless);TavilySearchProvider.connectivityTest() / probe() / usage() / status() 也提供了编程用的服务端路径,GET /api/tavily-status 为卡片状态指示器供数。浏览器侧因安全设计读不回已存密钥,故「测试API连接」按钮仍要求已配置密钥时重输一次。

映射

Tavily 的扁平 results[] 映射为规范化的 WebSearchSource:url ← url、title ← title、snippet ← 非空 content(无内容的条目被丢弃)、publishedAt ← published_date(news/finance 主题)。Tavily 生成式 answer(includeAnswer 开启时)成为结果 content。请求的 maxResults 优先于配置默认值,作为 Tavily max_results 发送;最终上限由 seam 强制执行。完整专业参数集被转发:search_depth(basic/advanced/fast/ultra-fast)、chunks_per_source、topic、time_range、start_date/end_date、days、include_answer(布尔或 basic/advanced)、include_raw_content(布尔或 markdown/text)、include_images、include_image_descriptions、include_favicon、include_domains/exclude_domains、country。注意:include_images/include_favicon 会发送给 Tavily,但当前 seam 的 WebSearchSource 尚无图片/favicon 字段,无法在规范化结果中呈现;暴露它们是为了让请求能带上这些参数。失败以 seam 的 WebError 呈现(WEB_PROVIDER_ERROR / WEB_ABORTED);请求超时报为 WEB_PROVIDER_ERROR。

路线图(规划中)

产品分析中确认的高置信后续项:

  • ✅ 用量/成本面板 —— 卡片展示 GET /usage + 实时积分/token 预估(已实现)。
  • ✅ 429 重试 + 短时缓存 —— retry-after 感知退避 + 可选 TTL 缓存(已实现)。
  • ✅ Extract 提取能力 —— 已在现有 fetch seam 上注册基于 Tavily Extract 的 WebFetchProvider(已实现)。
  • ✅ apiproxy 白名单摩擦 —— 提供幂等的 scripts/patch-apiproxy.mjs(已实现)。
  • ✅ 状态指示器 —— GET /api/tavily-status(已存密钥,不消耗搜索额度)+ 卡片徽标与刷新(已实现)。
  • ✅ 错误分类 —— 连通/用量失败分类为 Key 无效 / 余额不足 / 限流 / 服务宕机 / 超时 / 网络,并附分场景 UI 文案(已实现)。
  • ✅ 缓存加固 —— LRU 上限(cacheMaxEntries)+ 时效性查询绕行(cacheBypassFresh)(已实现)。
  • ✅ 参数预设 —— 卡片一键暂存「深度研究 / 快速摘要 / 新闻实时」(已实现)。
  • ✅ 精简调试日志 —— 可选 debug 开关,每次搜索/抓取输出一行可读日志(已实现)。
  • ✅ 多密钥轮换 & 故障转移 —— apiKeyRefs 凭据引用环,429/Key 无效/余额不足自动轮换,3 次失败进冷却(已实现)。
  • ✅ 脚注式引用(证据溯源) —— citeFormat: footnote 在摘要后追加编号来源块(已实现)。
  • ✅ 自动兜底引擎 —— fallbackEngine: deepseek 在超时/网络/5xx 时自动兜底(已实现)。
  • ✅ 可选 Firecrawl 抓取 —— firecrawl fetch 提供方(/scrape、markdown、独立凭据引用),未选择时惰性(已实现)。
  • ✅ 持久化结果缓存 —— cacheFile JSON 落盘、重启不丢,防抖且尽力而为(已实现)。

已暂缓(刻意为之,见优化评审):搜索后批量 extract(top-N 页面) 会改变结果语义(抓取文本必须注入 content)、按 URL 消耗 extract 额度,并把搜索与整页抓取隐式耦合——如需可另立可选开关再议。

开发

pnpm install
pnpm run build          # tsdown → lib/index.mjs(宿主端)+ lib/client.cjs(浏览器端,均提交入库)
pnpm run typecheck      # tsc --noEmit
pnpm run test:contract  # slot 契约漂移守卫(不需联网)
node tests/decode-check.mjs   # schema 往返校验(不需联网)
pnpm test               # 真实 API 冒烟:需要 TAVILY_API_KEY
node tests/profile-boot-smoke.mjs   # 安装→服务连通冒烟:需要 PLUGIN_TGZ
node tests/browser-e2e.mjs          # 真实浏览器加载结果门禁:需要 PLUGIN_TGZ + Chromium

浏览器 E2E(tests/browser-e2e.mjs)是复现 issue #1 场景的那一层:它能启动真实 dsh web、在真实浏览器里走完首启向导,并断言插件加载正常——"Failed to load plugins / list slot requires options.id" 横幅正是它要拦截的确切症状(已在真 rc.6 上双向验证:坏掉的 key-only 注册原样复现、修复后的双字段注册干净通过)。CI 的 browser-e2e 矩阵使用它;重载开发机上可能偶发的无头 Chrome 冻结,由阶段级时间预算、300s 看门狗与 CI 内的一次重试兜底。


`settings.plugin.item` 插槽契约在不同 DSH 发布版之间发生过漂移——`0.1.0-rc.6` 声明为 **list** 插槽(注册要求 `id`),而 `0.1.1-rc.x` 声明为 **keyed**(注册要求 `key`)。卡片注册**同时携带** `key` 与 `id`(外加 list 侧 `order`),因此同一份注册可被所有已发布运行时接受。`pnpm run test:contract` 会解析产物 `lib/client.cjs`,把其中的注册形状喂给真实 `SlotCore` 在两种声明形态下验证;CI 矩阵(`.github/workflows/ci.yml`)还会针对已发布的 `dsh-client-ui-slots` 核心(`0.1.0-rc.6` / `0.1.0-rc.8` / `0.1.1-rc.2`)重跑,并按发布版(`0.1.0-rc.6` / `0.1.1-rc.2`)各启动一次真实 dsh profile 验证实际服务的 bundle。

**发布完全自动化且经 CI 门禁**:改 `package.json` 版本号并推送到 `main`,`Release` 工作流(`.github/workflows/release.yml`)会先等待该提交的 CI 全绿,随后自动打 `v<版本>` tag 并发布 GitHub Release(自动生成变更记录 + 打包好的 tarball 附件)。节奏由 SemVer 决定:**patch** 修 bug(尤其是被 issue 锚定的修复——有人在等,如本次 settings.plugin.item 修复的 v0.6.1)、**minor** 一批功能落地、**major** 破坏性变更。`#main` 安装路径本来就会拿到每个合入的提交;tag 是"推荐版本"的不可变快照。

`lib/` 提交入库,插件安装时无需构建步骤(无 `prepare` 脚本,不需要 pnpm 构建脚本白名单)。`@deepseek-ai/*` 的 seam 与框架包**外部化** —— 由 harness 在运行时提供,声明为 `peerDependencies`。浏览器 bundle(`lib/client.cjs`)是 CJS 模块加载器工厂:只 `require()` 客户端模块表中的平台包,插件自身卡片代码内联其中,安装时无需额外解析。`@deepseek-ai/dsh-base` 只是 devDependency,供冒烟测试解析 harness 运行时闭包。

## 许可证

MIT

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。