Skip to content
dsh.fish
Bundle

dsh-see-world

开眼看世界:DSH 决策层插件——让 agent 在「该上网搜索」的时候先搜再答(fresh-info-first / 联网优先)。判定『何时搜索』(决策层),不自带搜索引擎(能力层)。

Source
windygo123
License
MIT
Updated
Updated yesterday

Readme

# 开眼看世界 · dsh-see-world

**「开眼看世界」——让 agent 在该上网搜索的时候先搜再答。把「靠自觉」变成「靠机制」,本地任务零打扰。**

**[English](README.en.md)** | **简体中文**

<p align="center">
  <a href="https://www.npmjs.com/package/dsh-see-world"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-see-world?style=flat-square&label=npm"/></a>
  <a href="https://www.npmjs.com/package/dsh-see-world"><img alt="npm downloads" src="https://img.shields.io/npm/dm/dsh-see-world?style=flat-square&label=downloads"/></a>
  <a href="https://github.com/windygo123/dsh-see-world/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/github/license/windygo123/dsh-see-world?style=flat-square"/></a>
  <a href="https://github.com/windygo123/dsh-see-world"><img alt="GitHub stars" src="https://img.shields.io/github/stars/windygo123/dsh-see-world?style=flat-square"/></a>
</p>

> 一个 **DeepSeek Harness(DSH)决策层插件**:它决定「什么时候该上网搜索」(而不是「怎么搜」),并且强制「先搜后答」。本地任务保持零打扰。

- **决策层**:判定「这条消息需不需要新鲜信息」,而不是「怎么搜」。不自带搜索引擎——**能力层**(Tavily / SearXNG provider / 内置 `web_search` 等)负责执行,本插件只决定时机,并强制「先搜后答」、回答引用来源。

---

## 特性

| | |
|---|---|
| 🎯 **先搜后答** | 判定需要联网的消息,在回答前强制注入「先搜索 + 引用来源 + 搜不到就明说『不确定』」,杜绝编造 |
| ⚡ **零打扰** | 本地任务(代码/文件/计算/闲聊)毫秒放行,不上网、不闪屏、不啰嗦 |
| 🧭 **当前信息优先** | 问最新消息、行情、版本、政策——默认先联网核实,再谈旧知识 |
| 🔍 **看得见的判定** | 判定期间呼吸状态条、「🔍 已搜索 N 个来源」标记、8 秒超时明示「判定超时」 |
| 🛡️ **故障不崩** | 搜索插件没装、判定器出错、模型超时——一律静默降级,对话照常 |
| 🖥️ **可视化配置** | 设置页卡片(设置 → 插件 →「开眼看世界」),保存即生效;每项带 ❓ 说明 + 判定模型「测试连接」 |
| 📈 **决策可观测** | 本地 JSONL 日志(判定理由/耗时/成本/是否搜索),只存本机、默认只记摘要 |
| 🔒 **隐私友好** | 判定默认复用会话模型;可用本地 Ollama 判定——数据完全不离开你的机器 |
| 📝 **可测试** | 26 道附录 B 用例回归锁定(漏网 ≤1、误触发 ≤1),误判案例可回流测试集 |

---

## 安装

```bash
dsh plugin --profile web add dsh-see-world
```

> 安装/更新后**建议重启一次 DSH GUI**(让浏览器半部——设置卡片、判定状态条——加载生效;见 [常见问题 ⑤](#已知限制faq))。

本地开发安装(仓库路径方式,先 `npm run build`):

```bash
dsh plugin --profile web add D:\dsh-open-eyes
```

---

## 零配置可用

**开箱即用,无需任何配置**:默认档位「宁多勿漏」(不确定即触发),判定器默认**复用会话模型**——不额外选模型、不增加额度消耗(用本地 Ollama 作判定器时,判定过程完全不离开你的机器,见 [CONFIG.md](CONFIG.md))。

纯本地任务(代码、文件、命令、计算、闲聊)默认不触发搜索;需要联网的消息先搜再答、末尾附「🔍 已搜索 N 个来源」。

---

## 配置项一览

完整白话解释(每项是什么、怎么填、对判定有什么影响)见 **[CONFIG.md](CONFIG.md)**;可视化卡片在 **设置 → 插件配置 → 「开眼看世界」**(命名空间 `open-eyes`,保存后**下一回合立即生效**,非法值会被拒绝保存;唯一例外:`log_dir` 保存后下次启动生效)。

| 配置项 | 默认值 | 说明 |
|---|---|---|
| `trigger_gear` | `lenient` | 触发档位:`lenient`(宁多勿漏,不确定即触发)/ `balanced` / `conservative`(宁可漏搜、少打扰) |
| `judge_model` | `''` | 判定器模型。空 = 复用会话模型;`provider/model`(如 `deepseek/deepseek-chat`)指定路由;`ollama/模型名`(如 `ollama/qwen3.5:4b`)直连本地 Ollama,判定不离开本机、不消耗会话模型额度 |
| `must_search` | `[]` | 领域白名单:命中这些关键词/领域一律搜索 |
| `never_search` | `[]` | 领域黑名单:命中禁止搜索(优先于白名单) |
| `budget` | `0` | 每会话搜索次数上限;`0` = 不限制。超限后自动降级为「标注不确定」,不再触发新搜索 |
| `context_turns` | `3` | 多轮上下文补判轮数(默认 3 ≈ 最近 2-3 轮) |
| `mark_reply` | `true` | 触发且实际搜索的回合,回复末尾附一行「🔍 已搜索 N 个来源」 |
| `log_dir` | `''` | 决策日志目录;空 = 插件默认路径 `~/.dsh/dsh-open-eyes/decisions/` |
| `log_input_verbatim` | `false` | 决策日志保存判定输入**原文**;默认只存摘要(隐私默认) |

### 消息级强制标记(优先于以上全部配置)

- 两字前缀兜底(百分百生效):消息以「**不搜**」开头 = 本条禁止搜索;以「**先搜**」开头 = 本条强制搜索(如「先搜 帮我看看这个报错」);
- 自然语言(主力):「这个不用搜 / 别搜了」或「先查一下 / 上网搜搜再答」即生效;
- 前缀与自然语言同时出现时,以前缀为准。

---

## 与搜索能力层插件的兼容

**本插件不自带搜索引擎**,与 DSH 搜索能力层插件互补:它决定「何时搜」,能力层负责「怎么搜」。

- 搜索执行复用 DSH 标准接口,候选顺序:① `ctx.web` 搜索缝(`@deepseek-ai/dsh-web` 的 `WebRuntime.search`,归一化 seam,provider 由 seam 自行选择——`dsh-tool-web` 的 `web_search` 也走这条缝);② 经 `ctx.tools` 注册的标准搜索工具(如 `web_search`);
- 与任意 provider 插件(Tavily / SearXNG / 内置 web 搜索等)联用时**无需额外配置**;探测到即生效;
- **未安装任何搜索插件**(或全部卸载):插件静默降级——判定照常工作(结果仅记日志),不注入、不报错、不干扰对话。

---

## 隐私声明

- **决策日志是本地文件**(JSON Lines,默认 `~/.dsh/dsh-open-eyes/decisions/decisions.jsonl`,可用 `log_dir` 改),**不上传任何服务器**;文件可随时删除,不影响插件运行;格式公开,字段见 [CONFIG.md](CONFIG.md);
- **判定输入默认只存摘要**(截断 + 上下文条数标注),原文保存需显式开启 `log_input_verbatim: true`;
- **本地 Ollama 判定**:`judge_model` 配 `ollama/模型名` 时,判定直连本机 Ollama 原生 `/api/chat`——**判定过程完全不离开你的机器**,也不消耗会话模型额度;Ollama 未启动时自动优雅降级(本轮不判定、不阻塞、不报错)。

---

## 已知限制 / FAQ

### ① 判定只看文字,图片内容不参与判定

判定器只读取消息里的**文字块**——图片内容不参与「要不要搜」的判定。因此**纯图片消息默认不搜**(也默认不消耗判定),发图即秒上屏、零打扰。**想让模型按图片内容去搜**:在消息里加「先搜」前缀并说明意图,如「先搜 这张图里的产品报价」——强制标记会百分百生效。

### ② 判定模型默认复用会话模型,可换本地/便宜模型

`judge_model` 留空 = 复用当前会话模型(零配置默认)。想控成本/提速,可在设置卡片「判定模型」里填 `provider/模型`(如 `deepseek/deepseek-chat`)或直连本地模型 `ollama/模型名`(如 `ollama/qwen3.5:4b`,判定不离开本机)。**改完先点卡片里的「测试连接」**,成功后再保存。

### ③ 判定超时 8 秒:跳过本轮、明示「判定超时」,不卡对话

语义判定有 8 秒硬超时。超时会**跳过本轮判定**(按不注入的降级路径放行)并在状态条明示「判定超时」,对话照常进行、不阻塞不报错。快速通道(明确本地任务 / 明显时效性查询)毫秒级完成,通常不会走到超时;若你的模型经常超时,优先考虑换更快的判定模型(见 ②)。

### ④ 插件不自带搜索,必须先装搜索能力插件

本插件只做「何时搜」的判定,不执行搜索。要真正搜到内容,需要 DSH 的**搜索能力层插件**(任何提供 `ctx.web` 搜索缝或 `web_search` 标准工具的能力插件,如 Tavily / SearXNG provider / 内置 web 搜索)。未安装搜索插件时本插件静默降级,不影响日常对话,但不会真的联网。

### ⑤ 设置卡片未显示:更新/安装插件后需重启 GUI

「开眼看世界」配置卡片属于浏览器半部,在 GUI 启动时加载。**安装或更新插件后若设置页看不到卡片,重启一次 DSH GUI 即可**(若插件正在运行/热更新中,同样先重启再找)。

### ⑥ 报错 `EADDRINUSE 127.0.0.1:3080`:旧的 DSH 进程没退出

端口 3080 被占用 = 之前启动的 DSH 进程还在运行(可能是旧窗口未真正关闭)。**先关闭旧的 DSH 窗口/进程**(任务管理器确认无残留 dsh 进程),再启动新的实例。

---

## 决策可观测(R4)

触发/未触发、理由、置信度、判定耗时与 token 成本、搜索是否实际发生、来源数……每回合追加一行到**本地 JSONL 决策日志**(`~/.dsh/dsh-open-eyes/decisions/decisions.jsonl`);可随时删除、不上传。触发搜索的回合回复末尾附「🔍 已搜索 N 个来源」。程序化读取:

```js
import { loadRecords, aggregateStats } from 'dsh-see-world'
const stats = aggregateStats(loadRecords()) // 默认日志路径;或 loadRecords('路径')
```

---

## 开发(本地)

```bash
npm install
npm run build            # tsc 编译 TypeScript → lib/
npm test                 # 全部单元测试(node --test,含 R1-R5 回归)
npm run test:regression  # 附录 B 判定器回归(fixture 离线确定性后端 + 报告)
npm run cases            # 决策日志 → 附录 B 候选样例回流(scripts/export-cases.mjs)
npm pack                 # 打包预览(发布内容)
```

> 测试集扩充机制、`npm run cases` 回流流程与代码踩坑(`session.append` / `inject` 声明)见 **[CONTRIBUTING.md](CONTRIBUTING.md)**。

---

## 目录结构

| 路径 | 说明 |
|---|---|
| `src/index.ts` | 插件入口(`name` / `Config` / `apply`;R2 回合流程 + R4 决策记录;SSE / 诊断 / 测试连接路由) |
| `src/config.ts` | 配置 schema + 默认值 + settings 命名空间注册(live 生效) |
| `src/judge.ts` | 信息差风险判定器(强制标记 / 领域规则 / 快速通道 / 快速触达 / 语义判定 / 档位 / 降级) |
| `src/model.ts` | 判定模型抽象 + 会话模型复用 + Ollama 直连 + 连通性测试(测试连接) |
| `src/search.ts` | 能力层唯一接缝:`ctx.web` 搜索缝 / 标准搜索工具探测与执行(不自带搜索) |
| `src/r2.ts` | 强制先搜后答注入 + 回合记账(触发/违规/预算) |
| `src/decision-log.ts` | R4 决策日志(JSONL 读写 / 会话统计 / 摘要) |
| `src/judge-bus.ts` `judge-signal.ts` `judge-sources.ts` | 判定动效信号:进程内总线 + SSE 路由(**不进会话日志**) |
| `src/settings-card.ts` `settings-form.ts` `client/OpenEyesCard.tsx` | 设置卡片(`❓` 悬浮说明 / 测试连接按钮 / 表单引擎) |
| `cordis.patch.yml` | DSH bundle patch:安装即挂载 |
| `tests/` `test/` | 单元测试 + 回合级集成测试 + 附录 B 回归(runner + samples) |
| `LICENSE` | MIT |

---

## 文档

- 需求文档(PRD v0.2,含 §6 开源与发布要求):`fresh-info-first-需求文档.md`
- 配置说明(白话逐项解释 + 测试连接用法):**[CONFIG.md](CONFIG.md)**
- 贡献指南(测试集扩充机制 / 踩坑注意事项):**[CONTRIBUTING.md](CONTRIBUTING.md)**
- 更新日志:**[CHANGELOG.md](CHANGELOG.md)**
- 英文版说明:[README.en.md](README.en.md)

## License

[MIT](LICENSE)

Install

dsh plugin --profile web add github:windygo123/dsh-see-world

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source