Workflow & Automation

dsh-open-eyes

windygo123/dsh-open-eyes · ★ 0

windygo123

DSH plugin: decide WHEN to search the web, enforce search-first answers, and stay out of the way for local tasks.

License
MIT
Added
2026-08-16
Maintenance
active
Install kind
github
Manifest details
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-08-19
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add github:windygo123/dsh-open-eyes

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Features
  2. Installation
  3. Zero Configuration
  4. Configuration Reference
  5. Message-level force marks (highest priority, above every config)
  6. Compatibility with Capability-Layer Plugins
  7. Privacy
  8. Known Limits / FAQ
  9. 1. Text-only judging — image content is not considered
  10. 2. Judge model: session model by default, local/cheap models supported
  11. 3. 8-second judge timeout — skips the turn, shows the notice, never blocks
  12. 4. No built-in search — install a search capability plugin
  13. 5. Settings card missing? Restart the GUI after install/update
  14. 6. EADDRINUSE 127.0.0.1:3080: an old DSH process is still running
  15. Decision Observability (R4)
  16. Development
  17. Repository Layout
  18. Documentation
  19. License

"Open Eyes on the World" — make your agent search the web first when it should, and answer with sources. Local tasks stay zero-disturbance.

English | 简体中文

A decision-layer plugin for DeepSeek Harness: it decides when to search (not how), and enforces search-first answers. Local tasks stay zero-disturbance.

  • Decision layer: it judges whether the current message needs fresh information; search execution is delegated to capability-layer plugins (Tavily / SearXNG provider / built-in web_search, etc.). This plugin decides the timing and enforces "search first, answer with sources, say 'uncertain' when nothing is found".

Features

🎯 Search-first answers When a message needs fresh info, a directive is injected before the reply: search first, cite sources, and say "uncertain" if nothing is found — no fabrication
⚡ Zero disturbance Local tasks (code / files / math / chat) pass through instantly — no search, no flicker, no noise
🧭 Fresh-info first Asking about latest news, prices, versions, policies? Defaults to verifying online before relying on stale knowledge
🔍 Visible judgment Breathing status bar while judging, "🔍 searched N sources" reply marker, and an explicit "judge timeout" notice after 8s
🛡️ Fault-proof No search plugin installed, judge errors, model timeout — everything degrades silently; the conversation never breaks
🖥️ Visual config Settings card (Settings → Plugins → "开眼看世界"), applies live on save; per-field ❓ help tooltips + a "Test connection" button for the judge model
📈 Observable decisions Local JSONL decision log (reason / latency / cost / whether searched), stored locally only, summaries by default
🔒 Privacy-friendly Judge reuses the session model by default; optionally use a local Ollama model — judging never leaves your machine
📝 Testable 26-case appendix B regression locks (≤1 miss, ≤1 false positive); misclassified cases can be re-imported into the test suite

Installation

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

After install/update, restart the DSH GUI so the browser half (settings card, judge status bar) loads (see FAQ #5).

For local development (repo path — run npm run build first):

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

Zero Configuration

Works out of the box. The default gear is lenient (search when unsure), and the judge reuses the session model — no extra model to pick, no extra quota (with a local Ollama judge, judging never leaves your machine; see CONFIG.md).

Pure local tasks (code, files, commands, math, chat) do not trigger search by default; messages that need fresh info are answered search-first, with a "🔍 searched N sources" marker appended.


Configuration Reference

Full plain-language explanations are in CONFIG.md; edit everything in the settings card (Settings → Plugin config → 开眼看世界, namespace open-eyes). Changes apply live on the next turn; invalid values are rejected on save (log_dir applies after restart).

Key Default Meaning
trigger_gear lenient Trigger gear: lenient (search when unsure, default) / balanced / conservative (less disturbance)
judge_model '' Judge model. Empty = reuse session model; provider/model (e.g. deepseek/deepseek-chat) sets a route; ollama/name (e.g. ollama/qwen3.5:4b) talks to local Ollama directly — judging stays on your machine, consuming no session-model quota
must_search [] Whitelist: matching messages always search
never_search [] Blacklist: matching messages never search (wins over whitelist)
budget 0 Max searches per session; 0 = unlimited. Over budget → mark "unverified/uncertain" instead of searching
context_turns 3 Recent turns carried into judging (3 ≈ last 2–3 turns)
mark_reply true Append "🔍 已搜索 N 个来源" to replies of triggered turns that actually searched
log_dir '' Decision log directory; empty = ~/.dsh/dsh-open-eyes/decisions/
log_input_verbatim false Log the full input text; default stores only a summary (privacy)

Message-level force marks (highest priority, above every config)

  • Two-char prefixes (guaranteed): start with 「不搜」 = never search this message; start with 「先搜」 = must search (e.g. 先搜 帮我看看这个报错 — "search first: look at this error");
  • Natural language (primary): "这个不用搜 / 别搜了" (don't search this) or "先查一下 / 上网搜搜再答" (look it up first) also work;
  • Prefix wins when both appear.

Compatibility with Capability-Layer Plugins

This plugin ships no search engine; it composes with DSH search capability plugins: it decides when, they perform how.

  • Search execution goes through the DSH standard seam: ① the ctx.web search seam (@deepseek-ai/dsh-web's WebRuntime.search; dsh-tool-web's web_search uses it too); ② a standard search tool registered via ctx.tools (e.g. web_search);
  • Works with any provider plugin (Tavily / SearXNG / built-in web search) with no extra config — detected automatically;
  • No search plugin installed (or all removed): the plugin degrades silently — judging still runs (logged only), nothing is injected, nothing errors, the conversation is unaffected.

Privacy

  • Decision logs are local files only (JSON Lines, default ~/.dsh/dsh-open-eyes/decisions/decisions.jsonl, configurable via log_dir), never uploaded; deletable anytime; public format (fields in CONFIG.md);
  • Judge input is stored as a summary by default (truncated, with context-turn count); verbatim text requires log_input_verbatim: true;
  • Local Ollama judging: with judge_model: ollama/name, judging hits the local Ollama native /api/chat — it never leaves your machine, and consumes no session-model quota; if Ollama is down, the plugin degrades gracefully (this turn is skipped — no block, no error).

Known Limits / FAQ

1. Text-only judging — image content is not considered

The judge reads text blocks only — image content does not affect the search decision. A pure-image message defaults to no search (and skips judging entirely): instant, zero-disturbance. To search based on image content, prefix the message with 先搜 + intent, e.g. 先搜 这张图里的产品报价 — the force mark always works.

2. Judge model: session model by default, local/cheap models supported

Empty judge_model reuses the session model (zero-config default). To cut cost/latency, set provider/model (e.g. deepseek/deepseek-chat) or a local model ollama/name (e.g. ollama/qwen3.5:4b, judging stays on your machine). Click "Test connection" after changing it, then save.

3. 8-second judge timeout — skips the turn, shows the notice, never blocks

The semantic judge has a hard 8s timeout. On timeout it skips judging this turn (degraded pass-through) and shows "判定超时" (judge timed out) in the status bar — the conversation continues normally. Fast paths (clear local tasks / obvious time-sensitive queries) complete in milliseconds; if your model times out often, switch to a faster judge model (see #2).

4. No built-in search — install a search capability plugin

This plugin only decides "when to search"; it never executes a search. To actually fetch content, install a DSH search capability plugin (anything exposing the ctx.web search seam or a web_search standard tool — Tavily, SearXNG provider, built-in web search, etc.). Without one, the plugin degrades silently: everyday conversation is unaffected, but nothing is really fetched online.

5. Settings card missing? Restart the GUI after install/update

The "开眼看世界" config card is part of the browser half and loads when the GUI starts. If the card does not appear in Settings after installing/updating the plugin, restart the DSH GUI once (also restart before looking for it if the plugin is mid-run / hot-reloading).

6. EADDRINUSE 127.0.0.1:3080: an old DSH process is still running

Port 3080 in use means a previous DSH process is still alive (an old window may not have fully closed). Close the old DSH window/process first (make sure no dsh process remains in Task Manager), then start a new instance.


Decision Observability (R4)

Triggered or not, reason, confidence, judge latency & token cost, whether a search actually happened, source count… each turn appends one line to the local JSONL decision log (~/.dsh/dsh-open-eyes/decisions/decisions.jsonl); deletable anytime, never uploaded. Turns that triggered and searched get a "🔍 已搜索 N 个来源" reply marker. Programmatic access:

import { loadRecords, aggregateStats } from 'dsh-see-world'
const stats = aggregateStats(loadRecords()) // default log path; or loadRecords('/your/path')

Development

npm install
npm run build            # tsc → lib/
npm test                 # full unit tests (node --test; R1–R5 regression)
npm run test:regression  # appendix B judge regression (offline deterministic fixture + report)
npm run cases            # decision log → appendix B candidate cases (scripts/export-cases.mjs)
npm pack                 # preview the published tarball

Test-suite expansion, the npm run cases workflow, and the two hard-won code pitfalls (session.append / inject declaration) are documented in CONTRIBUTING.md.


Repository Layout

Path Description
src/index.ts Plugin entry (name / Config / apply; R2 turn flow + R4 decision records; SSE / diagnostics / test-connection routes)
src/config.ts Config schema + defaults + settings namespace registration (live)
src/judge.ts Information-gap risk judge (force marks / domain rules / fast paths / semantic judging / gear / degrade)
src/model.ts Judge model abstraction + session-model reuse + Ollama direct connect + connectivity test
src/search.ts The only capability-layer seam: ctx.web search seam / standard search tool detection & execution (no built-in search)
src/r2.ts Search-first injection + turn accounting (triggered/violation/budget)
src/decision-log.ts R4 decision log (JSONL read/write / session stats / summaries)
src/judge-bus.ts judge-signal.ts judge-sources.ts Judge-visual signal: in-process bus + SSE route (never written to session logs)
src/settings-card.ts settings-form.ts client/OpenEyesCard.tsx Settings card (❓ help tooltips / test-connection button / form engine)
cordis.patch.yml DSH bundle patch: mounts on install
tests/ test/ Unit + turn-level integration tests + appendix B regression (runner + samples)
LICENSE MIT

Documentation

  • PRD (v0.2, incl. §6 open-source & release requirements): fresh-info-first-需求文档.md
  • Configuration guide (plain-language per-field + test-connection usage): CONFIG.md
  • Contributing guide (test-suite expansion / pitfalls): CONTRIBUTING.md
  • Changelog: CHANGELOG.md
  • 中文版说明:README.md

License

MIT