dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Tavily, Exa and Firecrawl as interchangeable ctx.web backends for DeepSeek Harness. Switch the engine behind web_search/web_fetch from a settings page, keys in the credential store, credential-free local fetch fallback.
DeepSeek Harness 的 web_search / web_fetch 与 Tavily / Exa / Firecrawl 之间的归一化中间层。
web_search ─┐ ┌─ tavily
├─ ctx.web 统一契约 ───────┤
web_fetch ─┘ (本插件负责转换) └─ exa / firecrawlauthor/warnings/failed_results 都折进同一处。include_answer 与 Exa 的 contents.highlights 都关闭,content 只承载降级 notice,正文一律走 web_fetch。dsh plugin --profile web add github:nhhc-lxr/dsh-web-tool-providerSettings → Plugins → 网页工具后端,一页三块:
┌ 后端选择 ─────────────────────────┐
│ web_search [ Tavily ▾ ] │
│ web_fetch [ Firecrawl ▾ ] │
├ API 密钥 ─────────────────────────┤
│ Tavily [已配置] ✎ 🗑 │
│ Exa [未配置] [____] ✓ │
│ Firecrawl [已配置] ✎ 🗑 │
└──────────────────────────────────┘没有保存按钮:两个下拉改动即存。密钥显式保存(避免输一半就被写进凭据库):已配置的行隐藏输入框,点铅笔才展开,同时在输入框左边显示剩余额度。
额度查询直连厂商接口(不经 ctx.web、不经工具层):
厂商 · 接口 · 剩余额度 Tavily · GET /usage · account.plan_limit - plan_usage(limit 为 null 表示不限) Firecrawl · GET /v2/team/credit-usage · 直接给 remainingCredits Exa · — · 无余额接口(要 service key + 团队开通,且只给美元消费额),页面显示「无额度接口」
密钥解析顺序:插件配置里的字面量 → 凭据库 → 环境变量(TAVILY_API_KEY / EXA_API_KEY / FIRECRAWL_API_KEY),每次调用重新解析。字面量密钥不会被写进状态文件。
界面只动后端与通用选项;下面的字段只从 profile 的 cordis.patch.yml 读取,作为首次运行的默认值:
层 · 字段 search · backend、includeDomains、excludeDomains fetch · backend、fallbackToHttp providers.tavily · baseURL、timeoutMs、maxChars、topic、searchDepth、apiKey、apiKeyEnv providers.exa · baseURL、timeoutMs、maxChars、searchType、apiKey、apiKeyEnv providers.firecrawl · baseURL、timeoutMs、maxChars、version、mainContent、maxAge、apiKey、apiKeyEnv
后端与通用选项存在插件自管状态文件(/.web-tool-provider/state.json,回退 $DSH_HOME、~/.dsh);状态文件优先于 Config。
SearchResult = { content?: string; sources: { url; title?; snippet?; publishedAt? }[]; truncated: boolean }
FetchResult = { url: string; statusCode: number; body: { kind: 'text' | 'html'; content: string }; truncated: boolean }snippet 单行、≤400 字;author 以 · 作者 附在末尾。publishedAt 一律 YYYY-MM-DD;Tavily 需显式请求 include_published_date 才有,Firecrawl 只有少数结果带。contents 之后,它的结果只剩链接、标题和日期。content 只装降级 notice(我们不向厂商要答案);抓取降级也会附 > provider notice: fell back ...。WEB_PROVIDER_UNAUTHORIZED / _QUOTA_EXCEEDED / _RATE_LIMITED / _BAD_REQUEST / _UPSTREAM / _UNREACHABLE / _EMPTY / _CREDENTIAL_MISSING、WEB_ABORTED、WEB_INVALID_URL、WEB_BLOCKED_URL。· 搜索 · 抓取 Tavily · max_results=5、search_depth(basic)、topic(general)、include_published_date · /extract Exa · numResults=5、type(auto),无 contents · /contents(text: true) Firecrawl · limit=5、sources=['web'] · /v2/scrape(markdown、onlyMainContent、48h 缓存)
这些都能在 YAML 里覆盖,见上一节。
html 会让工具层再转一遍。WEB_PROVIDER_CREDENTIAL_MISSING。本地抓取只做协议白名单、明文内网/回环地址拦截、逐跳重定向校验与字节上限,没有官方 dsh-web-fetch-http 的 DNS 解析+公网校验+连接钉扎。要那层保护就关掉 fallbackToHttp。
index.js:两层设置 + 归一化层 + 两个 provider + 两条 Host 路由,零第三方依赖。client.js:设置页(两个下拉 + 通用选项 + 三家密钥)。node test/smoke.mjs:20 项离线测试。改完代码需要重启一次 Harness 才会加载新的 host 实现;设置页刷新页面即可。
MIT