Skip to content
dsh.fish
Bundle

@helibeiqi/dsh-context-aware-search

Context-aware web search for DeepSeek Harness (dsh): rewrites queries with session context, reranks and credibility-tags results, and offers one-click source summarization across multiple backends.

Source
helibeiqi
License
MIT
Updated
Updated yesterday

Readme

# dsh-context-aware-search: Web Search That Actually Understands What You're Working On

A DeepSeek Harness (`dsh`) plugin that turns the `web_search` seam from a
dumb keyword blast into a **context-aware** research assistant. It reads your
current session, rewrites the raw query with what you're actually doing,
reranksthe results by relevance to that context, tags every source with a
credibility level, and can boil the top hits down into a one-click Markdown
brief.

> Same raw query, completely different — and far more useful — results when the
> plugin knows you're writing Rust instead of Go.

![Context-aware vs generic search](docs/demo-context-aware.svg)

---

## Why this exists

Generic web-search plugins return the *global* most-popular page for a keyword.
But when you search `error handling` while writing Rust, you don't want the
Wikipedia overview — you want `doc.rust-lang.org` and `thiserror` patterns.

`dsh-context-aware-search` closes that gap with four capabilities that ordinary
search plugins simply don't have:

- **Context-aware query rewriting** — the plugin reads your session's last N
  messages and expands the raw query with the technologies, languages, and
  libraries you're working with (e.g. `await 报错` →
  `Python asyncio await 常见错误 解决方案`).
- **Result reranking** — results are scored by TF-IDF similarity to the
  (rewritten) query *plus* your session context, so the most relevant source
  lands on top instead of whichever SEO won today.
- **One-click source summarization** — the model-callable `web_summarize` tool
  fetches a URL (or the top-N search hits) and returns a structured Markdown
  brief: key points, key data, and source links.
- **Source credibility tags** — every result is labeled `high` / `medium` /
  `low` by domain rules (`.edu` / `.gov` / official docs = high, known media /
  registries = medium, personal blogs = low), so you can triage at a glance.

It works **zero-config out of the box** (DuckDuckGo HTML needs no API key) and
fans out across up to three backends with automatic fallback.

---

## Comparison

| Capability | **dsh-context-aware-search** | built-in `web_search` (dsh-web-tools) | `dsh-web-search-deepseek` | `dsh-free-search`¹ |
|---|---|---|---|---|
| **Context-aware query rewriting** | ✅ | ❌ | ❌ | ❌ |
| **Result reranking by context** | ✅ (TF-IDF) | ❌ | ❌ | ❌ |
| **Source credibility tags** | ✅ high/med/low | ❌ | ❌ | ❌ |
| **One-click `web_summarize` tool** | ✅ | ❌ | ❌ | ❌ |
| Multiple backends + auto-fallback | ✅ DDG / Bing / SearXNG | provider-dependent | single (DeepSeek) | single |
| Zero-config (no API key) | ✅ (DuckDuckGo) | depends on provider | ❌ needs `DEEPSEEK_API_KEY` | ✅ |
| Settings Card (live config) | ✅ | n/a | ✅ | varies |
| DSH version pinned | ✅ `0.1.0-rc.6` | same runtime | same runtime | varies |

¹ `dsh-free-search` is a community no-key search plugin. The "❌" cells mark
capabilities that are, by definition, *not* part of a generic keyword search;
verify the upstream feature set before relying on this comparison.

---

## Install

> ⚠️ **Do NOT install `@latest`.** This plugin is built and type-checked
> against **DeepSeek Harness `0.1.0-rc.6`**. The `ctx.web` seam contract can
> change between releases; an unpinned or mismatched version can break search
> and fetch for your whole harness. Always pin the **plugin** version:
>
> ```bash
> dsh-context-aware-search@0.1.1
> ```

### Method 1 — GitHub Release tarball (recommended, no build step)

1. Download `dsh-context-aware-search-0.1.1.tgz` from the
   [Releases](https://github.com/helibeiqi/dsh-context-aware-search/releases) page.
2. Extract it into your dsh profile's plugin folder:
   ```bash
   mkdir -p ~/.dsh/profiles/node_modules/dsh-context-aware-search
   tar -xzf dsh-context-aware-search-0.1.1.tgz -C ~/.dsh/profiles/node_modules/ --strip-components=1
   ```
3. Add `dsh-context-aware-search` to your profile's `dsh.profile.bundles`
   array. Its bundled `cordis.patch.yml` re-pins the `web` seam to the
   context-aware providers as the active backends.
4. Restart dsh.

### Method 2 — From the DeepSeek npm registry (needs registry access)

The `@deepseek-ai/*` runtime packages live on the **DeepSeek registry, not**
public npmjs.com, so a plain `npm install` will not resolve the peer
dependencies. With registry access:

```bash
npm install dsh-context-aware-search@0.1.1 --registry <your-deepseek-registry>
```

then enable it in your dsh bundle as in Method 1, step 3–4.

---

## Configuration

All settings are optional — the schema supplies the defaults below, and they can
be changed live from the Settings Card (`ctx` → settings).

| Key | Type | Default | Meaning |
|---|---|---|---|
| `rerank` | boolean | `true` | Rerank results by TF-IDF similarity to query + context. |
| `credibility` | boolean | `true` | Tag each result with a high/medium/low credibility badge. |
| `rewriteEnabled` | boolean | `true` | Rewrite the raw query using session context. |
| `contextWindow` | number | `8` | How many recent session messages to read for context. |
| `backendOrder` | string[] | `['duckduckgo','bing','searxng']` | Backend priority for fallback. |
| `duckduckgoEnabled` / `bingEnabled` / `searxngEnabled` | boolean | `true` | Per-backend on/off. |
| `searxngInstance` | string | `''` | Base URL of a SearXNG instance (empty = disabled). |
| `bingApiKey` | string | `''` | Optional Bing key (empty = keyless scrape fallback). |
| `maxResults` | number | `10` | Max results returned per search. |
| `summarizeTopN` | number | `5` | Links the `web_summarize` tool pulls when given a query. |
| `userAgent` | string | `dsh-context-aware-search/0.1.1` | UA sent on fetch. |

---

## Usage

Just search as usual — the plugin does the rest.

**Session:**
```
User:  I'm writing a Rust CLI; my main() returns Result<(), Box<dyn Error>>.
User:  search error handling
```

**What the plugin does:**
1. Reads the last `contextWindow` messages → detects *Rust*, *cargo*, *Result*.
2. Rewrites `error handling` →
   `Rust error handling Result Option unwrap ? best practices`.
3. Runs the rewritten query across the backends (DuckDuckGo → Bing → SearXNG).
4. Reranks by context similarity and tags credibility.
5. Returns a banner + sources, e.g.:

```markdown
🔎 Context-aware rewrite: Rust error handling Result Option unwrap ? best practices

| # | credibility | title | url |
|---|----|----|----|
| 1 | 🟢 high | Error Handling in Rust - The Rust Book | https://doc.rust-lang.org/book/ch09-00-error-handling.html |
| 2 | 🟢 high | Recoverable vs Unrecoverable Errors | https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html |
| 3 | 🟡 medium | thiserror / anyhow patterns | https://crates.io/crates/thiserror |
```

**One-click brief** — ask the model to summarize:
```
User:  web_summarize query="Rust error handling best practices" topN=3
```
Returns a Markdown brief with key points, key data, and source links.

You can also summarize a specific page:
```
User:  web_summarize url="https://doc.rust-lang.org/book/ch09-00-error-handling.html"
```

---

## How it works

```
web_search(query)
   │
   ├─ context.ts      read last N session messages → plain-text context
   ├─ rewrite.ts      expand query with context terms (TF-IDF keyword extraction)
   ├─ backends/*      fan out to DuckDuckGo / Bing / SearXNG (priority + fallback)
   ├─ rerank.ts       TF-IDF score of each result vs (query + context) → reorder
   ├─ credibility.ts  domain rules → high / medium / low badge
   └─ search-provider.ts  assembles banner + pristine sources

web_summarize(url | query)
   ├─ fetch via ctx.web.fetch (context-aware-fetch provider)
   ├─ htmlextract.ts  pure-TS extractor → title / headings / paragraphs / lists
   └─ returns structured Markdown brief
```

No heavy NLP models, no external embedding service, no `ctx.llm` dependency —
just TypeScript and the platform `fetch`. Lightweight by design.

---

## Known limitations

- **No embedding model.** Reranking uses TF-IDF over the query + context, not
  semantic vectors. It's fast and dependency-free but weaker on paraphrase /
  intent mismatch than an embedding model would be.
- **Context text extraction is heuristic.** It only reads `text` content blocks
  from recent messages; images, tool outputs, and non-text blocks are ignored.
- **Search-result scraping is brittle.** DuckDuckGo / Bing HTML parsing can
  break if those sites change their markup; SearXNG JSON is more stable when
  you point `searxngInstance` at a reliable instance.
- **Summaries are extractive, not abstractive.** `web_summarize` pulls and
  structures the page's own text; it does not generate a free-form prose
  summary (no LLM call by design).
- **Credibility is rule-based.** It keys off domain suffixes / fragments; a
  high-value personal blog can be under-rated and a slick low-quality site
  over-rated. Treat badges as triage hints, not verdicts.

---

## License

[MIT](LICENSE) © dsh-context-aware-search contributors.

Topics: `dsh-plugin` · `deepseek-harness`

Install

dsh plugin --profile web add github:helibeiqi/dsh-context-aware-search

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