DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Tavily Resilient Search — DeepSeek Harness 插件(DSH Plugin)
← Plugins
T

dsh-tavily-resilient-search

Tavily Resilient Search

通过 Tavily API 为 DeepSeek Harness 提供实时网页搜索,支持密钥池的原子化、弹性轮换(速率限制 429、月度配额 432/433、撤销 401)以及无密钥应急方案——始终不中断 agent loop。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:frederico-kluser/dsh-tavily-resilient-search#ccca034fb8a0cc4a79ca371470bf87e34f9e0b63
README兼容性版本

兼容性与来源证明

Tavily Resilient Search 以 dsh-tavily-resilient-search 发布,当前版本为 0.1.3。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/9/24

版本

0.1.3stable
2026/9/24
0.1.2stable
2026/9/24
0.1.0stable
2026/9/24

相关插件

正在加载相关插件…

最新版
0.1.3
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/9/24
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

相关插件

继续浏览 search-research 分类下经过校验的插件。

Browser Skill Dsh Plugin@wxg-prc-cpg/browser-skill-dsh-plugin向模型提供 BrowserSkill 浏览器自动化(browser_* 工具)的 DeepSeek Harness 工具插件Weknora@wxg-prc-cpg/dsh-weknora适用于 DeepSeek Harness (dsh) 的 WeKnora 知识检索工具:通过自有知识库进行语义搜索、文档阅读以及 RAG/代理回答。Find Plugindsh-find-plugin在代理中查找 DeepSeek Harness 插件——实时搜索 GitHub 上的 dsh-plugin 主题,并按星标数排序。Dejadsh-dejaDeepSeek Harness 的 deja-vu 记忆:三十三个其他编码代理的会话历史,可搜索并在每个步骤前检索——本地索引,无需 LLM。

README

dsh-tavily-resilient-search

Pesquisa web em tempo real para o DeepSeek Harness (DSH), através da API Tavily, com rotação atómica e resiliente de um agrupamento de credenciais e contingência keyless — sem quebrar o agent loop quando as chaves atingem limites de taxa (429), esgotam a cota mensal (432/433) ou são revogadas (401).

Plugin Cordis autónomo: instala-se por manifesto, sem forks do código do DSH, e sobrevive a hot-reload/unload sem fugas nem escutas órfãs.


O problema que resolve

Numa implementação ingénua, um HTTP 429 ou 432 é propagado como rejeição de promessa à rotina de turnos: o turno termina abruptamente — ou o modelo conclui, erradamente, que "a internet deixou de existir". Aqui, a intenção semântica (pesquisar) está desacoplada da camada física (qual credencial despacha agora):

  • erros de saturação/faturação mutam o estado da chave causadora e a chamada é reemitida de imediato com o payload intacto, pela próxima credencial desimpedida (round-robin);
  • quando todo o pool está impedido, ativa-se a contingência keyless (X-Tavily-Access-Mode: keyless);
  • só quando todas as alternativas de transporte se esgotam é que a ferramenta devolve uma conclusão estruturada de aviso — nunca uma exceção que ejetasse o processo hospedeiro.

Instalação

dsh plugin --profile web add dsh-tavily-resilient-search

A ativação é automática: o pacote declara dsh.bundle.patch (apenas dsh.bundle.patch ativa um plugin — um bundle: {} vazio não ativa nada) e o manifesto cordis.patch.yml entra na camada Bundle da composição.

Defina as credenciais por variáveis de ambiente (nunca em texto simples):

export TAVILY_API_KEY_A="tvly-..."
export TAVILY_API_KEY_B="tvly-..."   # tantas quantas as contas disponíveis
export TAVILY_API_KEY_C="tvly-..."
export TAVILY_API_KEY_D="tvly-..."

Sem nenhuma chave o plugin não rebenta o boot: degrada para o modo keyless-only (limites muito mais severos) e avisa em voz alta. Estado legítimo documentado: "ainda não configurado".

Gestão de chaves via interface

Todo o CRUD do pool vive num único sítio: a secção “Tavily Keys” em Definições (Settings) — contribuída para o slot settings.section pelo bundle de cliente (client/client.js, formato __ModuleLoader__ medido no exemplo oficial), estilizada com o design system do DSH.

  • CRUD completo num só ecrã: adicionar (C, com Enter), listar com estados em cartões (R), editar/substituir (U, Enter guarda, Esc cancela), remover (D) e Testar (valida contra a API — 1 crédito).
  • Feedback em cada ação: spinner durante o pedido e confirmação ✓/⚠ imediata — nada de cliques sem resposta.
  • Botão “🔑 Tavily Keys” na área lateral só quando não existe chave válida (desaparece assim que há credencial utilizável); abre diretamente as Definições. Não há ecrã paralelo: a antiga página autónoma responde 410.
  • Links úteis no painel: app.tavily.com para obter chaves, documentação e onde está o token.

Token administrativo (para abrir o painel): gerado por CSPRNG no primeiro arranque, guardado em ~/.dsh/dsh-tavily-resilient-search/admin-token.txt (0600) e impresso uma vez no registo do DSH (logger 'tavily-pool'). Perdeu? Recarregue com DSH_TAVILY_ADMIN_RESET=1. Também pode definir DSH_TAVILY_ADMIN_TOKEN.

  • Fronteira: origem (socket + Origin) → Host → credencial, por esta ordem fixa; denegações byte-idênticas (sem oráculo). Predefinição: só loopback (admin.trustedRemotes / admin.allowedHosts).
  • Força bruta: orçamento NIST SP 800-63B-4 (100 falhas → lockout com o mesmo 401).
  • Ações destrutivas (remoção e substituição/edição) exigem nonce de confirmação, de uso único.
  • Auditoria: audit.log apensível (0600, O_NOFOLLOW) com todas as decisões mutáveis e denegações.
  • Chaves removidas que vêm do ambiente regressam no próximo arranque (a remoção é volátil e o painel avisa); chaves persistidas/removidas pelo painel são definitivas.
  • Sobre um bind público (0.0.0.0) o painel recusa-se a subir (fail-closed, ruidoso) até admin.allowPublicBind: true — a ferramenta de pesquisa continua a funcionar em qualquer caso.

Configuração

Sobreponha qualquer campo na camada Profile ($DSH_HOME/profiles/<nome>/cordis.patch.yml), Home ($DSH_HOME/cordis.patch.yml) ou CLI overlay (dsh --patch ./o.yml). A resolução é de entrada inteira (whole-entry replace), nunca deep-merge: aponte sempre ao id do próprio plugin.

CampoTipoPredefiniçãoFunção
apiKeysstring[][]Agrupamento de credenciais (round-robin). Vazio = keyless-only.
searchDepthultra-fast|fast|basic|advancedbasicProfundidade predefinida quando o modelo não escolhe.
maxResults1..100 (clamp a 10)5Máximo de fontes qualificadas.
includeAnswerbooleantrueInjeta a resposta preliminar sumarizada.
timeoutMs250..30000015000Timeout por tentativa HTTP.
callTimeoutMs≥ timeoutMs120000Orçamento cooperativo total da chamada (todas as rotações).
projectIdstring—Segregação por projeto (X-Project-ID).
admin.enabledbooleantruePainel de gestão de chaves via interface.
admin.trustedRemotesstring[]loopbackOrigens de soquete admitidas no painel.
admin.allowedHostsstring[]127.0.0.1, localhost, ::1Nomes de Host admitidos (anti DNS-rebinding).
admin.stateDirstring$DSH_HOME/dsh-tavily-resilient-searchDiretório de estado (0700).
admin.allowPublicBindbooleanfalseOpt-out explícito da recusa de bind não-loopback.
securityProfile

Exemplo (camada Bundle, já incluído no pacote):

- insert:
    - id: dsh-tavily-resilient-search
      name: 'dsh-tavily-resilient-search'
      config:
        searchDepth: 'basic'
        maxResults: 5
        includeAnswer: true
        timeoutMs: 15000
        callTimeoutMs: 120000
        securityProfile:
          sandbox: 'workspace-write'
          approval: 'ask'
        apiKeys: !!js >
          (() => { try { return [process.env.TAVILY_API_KEY_A, process.env.TAVILY_API_KEY_B, process.env.TAVILY_API_KEY_C, process.env.TAVILY_API_KEY_D].filter(Boolean) } catch { return [] } })()

Regras medidas do manifesto (@deepseek-ai/dsh 0.1.x-rc): a ordem das linhas não carrega semântica de carga (a ativação é dirigida por inject) e um !!js que lança na carga impede o boot do DSH para todos os instaladores — a expressão acima é defensiva e devolve [] em falha.

Ferramenta exposta: web_search

ParâmetroTipoObrig.Descrição
querystringsimTermos objetivos (recomendado < 1500 caracteres; limite duro 4000).
search_depthenumnãoultra-fast/fast (< 800 ms) · basic · advanced (só documentação complexa).
max_resultsintegernão1 a 10 (predefinição 5).
topicenumnãogeneral | news.

Resultado canónico (forma total, null explícito quando não aplicável): ok, query, answer, sources[] (title, url, snippet, score), responseTime, resultsTruncated, keylessFallbackUsed, error, detail, suggestion. A projeção para o modelo inclui sempre um aviso de não-confiança sobre o conteúdo web (contenção de injeção indireta).

Comportamento por código HTTP

HTTPCondiçãoComportamento do plugin
200SucessoDescodifica, normaliza, aplica teto de 50 KB, devolve resultados.
400Parâmetros malformadosNão rotaciona — devolve erro + sugestão de correção.
401Chave inválida/revogadaBanida em definitivo (REVOKED) e avança já para a próxima.
403Domínio/rota interditaNão rotaciona — informa impossibilidade de acesso.
429Limite de taxaLê Retry-After (segundos ou data HTTP), arrefece a chave e rotaciona.
432Cota mensal esgotadaSuspende até à meia-noite UTC do mês seguinte e rotaciona.
433Teto PAYGO atingidoIgual a 432 (suspensão temporizada).
5xxInstabilidade transienteNova tentativa com a alternativa; estado da chave não muda.

Máquina de estados do agrupamento

                ┌──────────────┐  401   ┌──────────┐
      ┌────────►│    ACTIVE    │───────►│ REVOKED  │ (definitivo)
      │         └──────┬───────┘        └──────────┘
      │  cooldown      │ 429
      │  expirado      ▼
┌─────┴────────┐  ┌──────────────┐
│ (round-robin)│◄─│ RATE_LIMITED │  T = Retry-After ou min(Tmax, T0·2^k) + δ
└──────────────┘  └──────────────┘
      ▲
      │ reposição mensal (1.º dia, UTC)
┌─────┴───────────┐
│ QUOTA_EXHAUSTED │  432/433 → suspensa até à meia-noite UTC do mês seguinte
└─────────────────┘

T₀ = 500 ms, T_max = 60 s, jitter δ ∈ [0, 500) ms contra ressaturação em bloco. A recuperação é lazy (sem timers): a expiração é aplicada na seleção seguinte, o que mantém leituras puras e o event loop limpo.

Segurança

Resumo (completo em docs/seguranca.md):

  • A conjugação sandbox: danger-full-access + approval: never é recusada no load (fail-loud, irrecuperável de propósito). O securityProfile é uma atestação obrigatória do operador — configuração ausente também falha alto.
  • Canário de segredos por valor: material de credencial é redigido de todo o texto de saída e registos (um corpo de resposta malicioso que ecoasse a chave do Authorization nunca a propaga); identificação em logs apenas por máscara …últimos4.
  • Teto volumétrico de 50 KB por invocação: documentos-bomba não saturam a janela de contexto (include_raw_content nunca é enviado).
  • Conteúdo web é dado não-confiável: a projeção do modelo carrega aviso permanente contra injeção indireta de instruções.
Sandbox \ Approvalasknever
workspace-writePrudencial (padrão)Automação controlada
danger-full-accessAlargado vigiadoPROIBIDO — recusa de carga

API validada por medição (nunca por prosa)

A superfície usada foi lida dos .d.ts dentro dos tarballs npm publicados (sha256 registado em types/; reverificado por pnpm run check:upstream) e é travada por um contract test que falha se a API pública divergir. Factos medidos que corrigem documentação circulante:

Afirmação mortaComportamento real medido
inject: ['tools', 'logger']logger não é Service do Cordis: a fiber ficaria PENDING para sempre. Usa-se ctx.logger(nome); inject = ['tools'].
dsh.bundle: {} ativa o pluginSó dsh.bundle.patch ativa (medido em @deepseek-ai/dsh 0.1.0-rc.7+).
required: false nos parâmetrosO DSL marca obrigatoriedade com required?: true — opcional = omitir a chave.
output: { schema: { type: 'object' } }Objetos exigem additionalProperties: boolean explícito.
ctx.httpServer / spawn(cmd, args)ctx.webServer / ctx.subprocess.spawn(spec) (verificados na gama 0.1.x-rc).

Linhas suportadas: @deepseek-ai/dsh-tools ^0.1.1-rc.1 || ^0.1.7-rc.1 (o drift entre ambas é apenas aditivo) e @deepseek-ai/cordis ~4.0.4. Nota: o dist-tag latest dos subpacotes dsh-* aponta para a publicação mais antiga — a linha viva é next.

Desenvolvimento

pnpm install
pnpm run gate          # lint + typecheck + build + test + check:tarball
pnpm run check:upstream # reverifica tarballs/sha256 pela rede (Q-1)

Testes em quatro camadas (node:test + tsx, determinísticos — relógio e RNG injetados, sem sleeps):

CamadaProva
test/unitnúcleo puro: máquina de estados, teto de bytes, validação fail-loud, token/nonce/lockout, persistência 0600 + auditoria à prova de symlink
test/integrationrotação atómica sobre um double de transporte e o router do painel sobre servidor HTTP real (porta 0)
test/adversarialtenta brechar: canário de segredos, documento-bomba, injeção indireta, perfil YOLO, regressão P-09, boot-safety, CSRF/rebinding byte-idêntico, força bruta sem oráculo, nonce, recusa de bind público
test/contractos espelhos types/ correspondem verbatim aos .d.ts publicados

Empacotamento e publicação

Publica-se pré-compilado (dist/), sem scripts de build na instalação do consumidor (risgo de cadeia de suprimentos). files é uma allowlist: dist/, cordis.patch.yml, README.md, LICENSE, CHANGELOG.md. O gate de release é pnpm run gate && publint && attw --pack . && node scripts/check-tarball.mjs (este último inspeciona o tarball real). Notas de versão via changesets; em 0.x, um minor é breaking. Releases em CI usam trusted publishing (OIDC) — configurar uma vez no console do npm para este repositório.

Licença

MIT

{sandbox, approval}
obrigatório
Atestação do perfil de instalação (ver Segurança).