# dsh-tool-retriever

[English](README.md) | 中文

`dsh-tool-retriever` 是一个早期 Alpha 阶段的 DeepSeek Harness 插件，注册真实可调用的 `tool_search`。默认路径使用完整名称 Exact、Field-aware BM25F，以及面向大目录的 DSH LLM Query Rewrite；固定本地多语言 E5 只作为显式开启的实验能力保留。

## 状态与兼容性

当前开发版本是 `0.1.0-alpha.1`，精确面向：

- DeepSeek Harness：`0.1.0-rc.6`
- `@deepseek-ai/cordis`：`4.0.1`
- Node.js：`^22.19.0 || >=24.0.0`

npm 的 `next` 仍指向已发布的 `0.0.1-alpha.0`。当前开发版本尚未推送、打 Tag 或发布。

插件每次读取调用 Agent 的实时 Tool Registry，只排除 `tool_search`。它不会安装 restriction，也不会隐藏原生工具。TopK 动态激活仍等待 DSH 提供安全生命周期边界。

## 默认检索链路

```text
原始 Query ──→ Exact + BM25F ────────────────┐
    └─ 目录数量 >= 32                        │
       └─ DSH LLM Rewrite → BM25F ──────────┼─→ Weighted RRF → TopK
    └─ 显式开启实验 Dense → E5 ──────────────┘
```

原始 Query 始终参与检索。通过校验的 Rewrite 只扩展 BM25F 词法证据，不替换原始 Query，也不会进入 Exact 通道。原始 Query 已完整命中工具名时会直接跳过 LLM。

Rewrite 只调用 DSH 已注册的 `llm` 服务，不在插件里配置 API Key、Base URL 或厂商 SDK。显式配置的 `rewrite.provider/model` 优先；未配置时复用调用 Agent 的 provider/model。DSH LLM、路由、模型调用或输出不可用时，结果会明确标记失败，并保留原始 Exact/BM25F Query；如果显式开启了 Dense，它仍作为独立通道继续执行。

## 安装

```sh
dsh plugin --profile <profile> add dsh-tool-retriever@next
```

安装尚未发布的本地构建：

```sh
pnpm pack
dsh plugin --profile <profile> add ./dsh-tool-retriever-0.1.0-alpha.1.tgz
```

目标 Profile 必须提供 `tools`。`llm` 在插件加载时是可选服务，只在实际 Rewrite 时读取；凭证仍由选中的 DSH Provider 管理。

## 模型可见接口

```ts
interface ToolSearchInput {
  query: string
}

interface ToolSearchOutput {
  query: string
  catalogSize: number
  catalogRevision: string
  rewrite: {
    status: 'skipped' | 'applied' | 'failed'
    reason: 'disabled' | 'catalog-below-threshold' | 'exact-match' | 'applied'
      | 'llm-unavailable' | 'route-unavailable' | 'llm-error' | 'invalid-response'
    query: string // 只有 applied 时非空
  }
  results: Array<{
    name: string
    description: string
    rank: number
    score: number
    rrf: number
    exact: number
    bm25: number
    dense: number // Dense 关闭时固定为 0
    matchedFields: Array<'name' | 'description' | 'parameterName' | 'parameterDescription'>
  }>
}
```

每次调用都会重新读取 `tools.schemas(agent)`，并根据与 locale 无关的 code-unit 工具名顺序、原始描述和规范化输入 Schema 计算稳定的 SHA-256 revision。空 Query 是 Tool Error；本次搜索没有 Dense 向量时，没有 Exact/BM25F 证据会正常返回空结果。

## 配置

```yaml
topK: 8
bm25K1: 1.2
bm25B: 0.75
fieldWeights:
  name: 4
  description: 2
  parameterName: 1.5
  parameterDescription: 1
rewrite:
  enabled: true
  minCatalogSize: 32
  provider: ''
  model: ''
  maxTokens: 128
dense: false
fusion:
  rankConstant: 60
  weights:
    exact: 3
    bm25: 1
    dense: 1
```

`rewrite.provider` 和 `rewrite.model` 必须同时配置。两者为空时复用调用 Agent 的路由。Rewrite 输出必须是严格 JSON，只允许一个去除首尾空白后长度为 1–512 的 Query；辅助模型调用不会携带任何工具。

DSH Patch 覆盖配置行时会替换完整 `config`，因此需要重新写出所有要保留的字段。

## 实验 Dense

Dense 默认关闭。关闭时，插件不会创建 Embedding Provider、构建向量索引、加载 Transformers.js、访问 Hugging Face 或驻留模型内存。一旦显式开启，Dense 会对每个非空目录执行，不受 Rewrite 成败影响。

如需实验当前 E5 Provider，需要额外安装可选 peer `@huggingface/transformers@4.2.0`，再把 `dense: false` 改成：

```yaml
dense:
  offline: false
  cacheDir: ''
  batchSize: 16
  maxCachedCatalogs: 8
```

该 Provider 仍然会在插件 Fiber 内加载 `Xenova/multilingual-e5-small` q8，因此不代表 DSH 的长期架构。生产级 Dense 应等待 DSH 提供平台级 Embedding Seam，并由共享、隔离的 Provider 承担模型生命周期，而不是让每个适用 Fiber 自带本地模型。

## 失败和生命周期

- Rewrite 失败会通过 `rewrite.status/reason` 明确呈现，并保留原始 Exact/BM25F Query；显式开启的 Dense 仍继续执行。
- 显式开启的 Dense 失败仍然是 Tool Error，不会静默伪装成功。
- 两类失败都不会影响原生工具的可见性和执行。
- 插件卸载时先注销 `tool_search`，再终止并等待自身 Rewrite/索引任务，最后释放已启用的 Dense Provider。

## 开发与评测

```sh
pnpm install --frozen-lockfile
pnpm run verify:self-contained
pnpm run typecheck
pnpm test
pnpm run build
pnpm run prepare
pnpm pack --dry-run --json
```

普通测试使用确定性的 Fake DSH LLM，不需要凭证。已有真实 E5 检查只针对实验能力：

```sh
pnpm run test:e5
pnpm run eval:verify
pnpm run eval:dense
pnpm run eval:rewrite:prepare
pnpm run eval:rewrite:score
```

冻结语料包含 9 个领域、56 个工具和 168 条查询。Rewrite 对照固定使用 `deepseek-official` / `deepseek-v4-flash` 和 `query-rewrite-v1` Prompt。所有请求必须通过 DSH 已注册的 `llm` 路由执行，插件和评测器都不直接读取厂商凭证。评分器会比较原始 BM25 与真实 Rewrite 路径，并拒绝缺失或路由不一致的结果。

第一次冻结评测的跨语言 Recall@5 为 71.43%，由于 112 次 Rewrite 中有 51 次结构化输出无效，没有达到 80% 发布门槛。因此 `0.1.0-alpha.1` 当前不可发布。执行方式和结果分别见 [evaluation/README.md](evaluation/README.md) 与 [evaluation/RESULTS.md](evaluation/RESULTS.md)。

更多内容见 [DESIGN.zh-CN.md](DESIGN.zh-CN.md)、[CONTRIBUTING.md](CONTRIBUTING.md)、[SECURITY.md](SECURITY.md) 和 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。

## 许可证

[MIT](LICENSE)
