WeKnora
Tencent
Open-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.
tianjiqx/dsh-wigolo
DSH 联网搜索私有化方案,代理 web_search/web_fetch 至 Wigolo,覆盖搜索/抓取/提取/深度研究/缓存/监控全链路,数据不出域,零查询成本。 Wigolo-powered DSH search plugin — self-hosted search/crawl/extract/research/cache/watch pipeline, fully replaces built-in web_search/web_fetch. Zero cost, full data privacy.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:tianjiqx/dsh-wigolo
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
Self-hosted web search for DSH (DeepSeek Harness). This plugin integrates a privately deployed wigolo meta-search daemon into DSH, replacing the built-in web search with your own self-hosted search infrastructure — full control over search engines, caching, and data privacy.
Core purpose: Proxy and replace DSH's built-in
web_search/web_fetchwith a self-hosted wigolo daemon. One toggle switches all agent web searches to your private deployment — no cloud dependencies, no API keys, zero cost per query.
dsh web GUI ── sidebar panel ── /api/dsh-wigolo/* ──┐
│
agent tools (wigolo_search, …) ── MCP streamable-http ──► wigolo daemon
web seam (web_search / web_fetch) ───────────────────┘ 18+ engines · RRF · local cache
wigolo_search, wigolo_crawl, wigolo_extract, wigolo_research, wigolo_find_similar, wigolo_cache, wigolo_watch) expose trimmed, model-friendly parameter surfaces. Write operations stay agent-only; read-only cache/watch browsing also lives in an opt-in "Wigolo Cache" conversation tab (off by default).web_search / web_fetch through wigolo with one switch (on = wigolo drives both, off = official providers), toggled from the GUI with automatic cordis routing management.enabled, announceToAgent, and guidance override live in the official DSH settings UI (dsh-ssh pattern). Hot-reload: change settings, no restart needed.local, numeric offset like +8, or IANA name like Asia/Shanghai) so wigolo_cache results display in your local time.A running wigolo daemon (v0.2+), reachable over HTTP with a bearer token. Local (127.0.0.1:3333) is the default and needs zero extra setup.
dsh plugin --profile web add @tianjiqx/dsh-wigolo
dsh plugin --profile web add github:tianjiqx/dsh-wigolo
Both methods install the plugin and automatically register it in the profile's bundle list (via the plugin's bundled cordis.patch.yml). No manual editing required.
git clone https://github.com/tianjiqx/dsh-wigolo.git
cd dsh-wigolo
pnpm install
pnpm build
dsh plugin --profile web add link:$PWD
This clones the repo, builds it, and registers the plugin in the profile's bundle list automatically via link: (no manual cordis.patch.yml editing needed).
Put your daemon token into ~/.dsh/wigolo-token (first line, 0600):
echo "YOUR_TOKEN" > ~/.dsh/wigolo-token && chmod 600 ~/.dsh/wigolo-token
Restart dsh, open the Wigolo entry in the sidebar, and hit Test connection.
dsh plugin --profile web remove @tianjiqx/dsh-wigolo
This removes the plugin and its bundle registration. The token file ~/.dsh/wigolo-token and config ~/.dsh/wigolo.json are preserved (delete manually if desired).
For detailed usage scenarios and examples, see the Usage Guide (中文).
All settings can be configured through the Wigolo sidebar panel (click the Wigolo icon in the sidebar):
Changes take effect immediately (hot-reload), except for the takeover switch which requires a restart.
For advanced settings not exposed in the UI (e.g., per-tool defaults, timeout overrides), edit ~/.dsh/wigolo.json directly:
{
"version": 2,
"connection": {
"host": "127.0.0.1", // daemon address
"port": 3333,
"hostHeader": "auto", // auto | none | "<literal>"
"tokenFile": "" // "" = ~/.dsh/wigolo-token
},
"takeover": false, // true = wigolo drives web_search + web_fetch; false = official providers
"tools": {
"wigolo_search": { "enabled": true, "defaults": { "max_results": 10, "search_depth": "balanced" } },
"wigolo_crawl": { "enabled": true, "defaults": { "max_pages": 50 }, "timeoutMs": 300000 },
"wigolo_extract": { "enabled": true },
"wigolo_research":{ "enabled": true, "timeoutMs": 600000 },
"wigolo_find_similar": { "enabled": false },
"wigolo_cache": { "enabled": true },
"wigolo_watch": { "enabled": true }
},
"cacheTab": { "enabled": false }, // "Wigolo Cache" read-only GUI tab (default off; hot-apply)
"announceToAgent": true,
"timezone": "local" // cache timestamp timezone: "local" | "+8" | "-5" | "+5.5" | "Asia/Shanghai"
}
Per-tool defaults merge under the model's explicit arguments (the model always wins); timeoutMs overrides the built-in per-tool budget.
takeover is a simple boolean:
| Value | web_search |
web_fetch |
Notes |
|---|---|---|---|
true |
wigolo | wigolo | full replacement |
false |
official | official | wigolo_* tools only (default) |
Why a switch at all: when several providers register into the web seam and none is explicitly routed, web_search fails with WEB_PROVIDER_AMBIGUOUS. Takeover on (true) therefore also writes a self-managed block into ~/.dsh/cordis.patch.yml (searchProvider: wigolo, dsh-skin-style managed markers); takeover off (false) removes it and registers nothing, so it coexists safely with the official provider. Routing changes need a dsh restart — the panel tells you when.
The wigolo daemon persists cache timestamps as zone-less UTC ("YYYY-MM-DD HH:MM:SS"). The plugin converts them to the configured timezone before returning to the agent or rendering in the UI.
| Value | Example | Description |
|---|---|---|
"local" |
"local" |
Use the DSH host's system timezone (default) |
| Numeric offset | "+8", "-5", "+5.5" |
Fixed offset from UTC; supports half-hour zones |
| IANA name | "Asia/Shanghai", "America/New_York" |
Full timezone with DST rules |
Changes to timezone take effect after a dsh restart.
wigolo guards against DNS-rebinding by allowlisting Host values: localhost, the loopback literals, and its own bind host. Two consequences:
0.0.0.0 on a LAN machine accepts requests whose Host header is 0.0.0.0.fetch() refuses to set Host (Fetch spec), so the plugin uses node:http, which allows it.hostHeader: "auto" (default) sends no custom header for local daemons and the bind-host trick for remote ones. Set a literal only if your deployment needs it.
| Tool | Wigolo capability | Highlights | Timeout |
|---|---|---|---|
wigolo_search |
search | category / time_range / domain filters / depth tiers / "a \| b" multi-variant queries |
60s |
wigolo_crawl |
crawl | site crawl with patterns, strategy, page caps; every page lands in the cache | 300s |
wigolo_extract |
extract | CSS selector or field-schema structured extraction | 60s |
wigolo_research |
research | decomposes, searches in parallel, synthesizes a cited report | 600s |
wigolo_find_similar |
find_similar | related content from URL or concept (default off) | 120s |
wigolo_cache |
cache | search the local cache before hitting the network; stats / clear | 30s |
wigolo_watch |
watch | persistent URL change monitoring; pair with a scheduled agent task for notifications | 120s |
All timeouts are configurable per tool via timeoutMs in the config.
sec-fetch-site + origin checks) — they read/write private config and must never be served to LAN-exposed deployments.~/.dsh/wigolo-token (0600); API responses never include it.wigolo_cache clear is destructive; the tool description tells the model to confirm first.pnpm install
pnpm test # vitest (61 tests)
pnpm typecheck # tsc --noEmit
pnpm build # lib/index.mjs + lib/client.js (CSS inlined)
node test/smoke-real-daemon.mjs # manual smoke against a live daemon
Apache-2.0
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: meta-search。