# dsh-tool-ddgs DuckDuckGo web search and URL fetch tools for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). Zero required system dependencies — search is pure Node.js, fetch uses `@mozilla/readability` with optional `trafilatura` fallback for higher quality extraction. ## Install ```bash dsh plugin --profile web add github:BharathBillawa/dsh-tool-ddgs ``` Then restart dsh. The bundle patch automatically: - Registers `web_search` (DuckDuckGo Lite, pure Node) - Registers `web_fetch` (content extraction, saves to file) - Wires the native Search action to use ddgs - Disables the built-in DeepSeek web search provider - Enables the file read tool for accessing full fetched content ## Requirements - Node.js >= 24 (required by DeepSeek Harness) - **Optional**: Python 3.9+ with `pip install trafilatura` for better content extraction ## Tools ### `web_search` Search the web using DuckDuckGo Lite. Pure Node.js — no Python, no subprocess, no API key. - Accepts 1-4 queries - Returns deduplicated sources with titles, URLs, and snippets - Wired to the native Search action via `ctx.web` provider ### `web_fetch` Fetch a URL and extract readable text content: 1. Downloads the page with browser-like headers 2. Extracts clean text using `trafilatura` (if available) or `@mozilla/readability` 3. Saves the **full content** to `/tmp/dsh-web-fetch/.md` 4. Returns a **5000-char preview** + the file path + total line count If the preview answers the question, the model responds immediately. If more detail is needed, the model uses dsh's built-in `read` tool with `offset`/`limit` to read specific sections from the saved file — just like reading any local file. This avoids dumping 100K+ chars into context for a simple question about one section of a long article. ## How it works - **Search**: Direct POST to DuckDuckGo Lite + HTML regex parsing. No headless browser, no API key, no subprocess. - **Fetch**: Node native `fetch()` → `@mozilla/readability` (DOM extraction via `linkedom`). Falls back to `trafilatura` via Python subprocess when available (better quality on complex pages). - **File storage**: Full fetched content is saved to `/tmp/dsh-web-fetch/.md` ## Architecture The plugin registers both: - A **`ctx.web` search provider** (`id: "ddgs"`) — powers the native Search action in the agent loop - **`web_search` and `web_fetch` tools** — directly callable by the model ## Configuration The bundle patch configures itself. No manual `cordis.patch.yml` editing needed. ## License MIT