dsh-web-search-ddg
aooyoo
Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no m…
PROJECT TOPICS
PROJECT README
Generic webhook receiver for DeepSeek Harness — POST to a local endpoint and wake a dsh agent. CI, monitoring, or any HTTP-capable service can feed messages to a harness agent over plain HTTP. Zero runtime dependencies beyond the official schema library (node:http only).
dsh-webhook-bridge exposes a small local HTTP server. Each request to POST /hook/:channel delivers a message to that channel's agent session; committed assistant text can be streamed back to an optional callback URL. It is a protocol driver in the dsh extension model — the same role as the official ACP/JSON-RPC bridges, but for any system that can send HTTP.
Who is it for?
What it does
POST /hook/:channel (Bearer-secret auth) and GET /health.followup() into the same session.message > text > content; non-JSON bodies are used verbatim.reply_url in the body: committed assistant text is POSTed back as {"text": "..."}.What it does not do (yet)
fetch, node:http).@deepseek-ai/dsh@0.1.0-rc.6 / @deepseek-ai/cordis@^4.0.1.Install into a dsh profile (local checkout):
cd /path/to/deepseek-harness
pnpm dsh plugin --profile web add /path/to/dsh-webhook-bridge
From GitHub (source install — pnpm runs the prepare script, so allow it once):
pnpm dsh plugin --profile web add github:<you>/dsh-webhook-bridge
# pnpm ≥10 blocks the build script on first install; copy the printed package key
# into <profile>/pnpm-workspace.yaml under allowBuilds, then re-run.
Uninstall:
pnpm dsh plugin --profile web remove dsh-webhook-bridge
Pick a shared secret (e.g. openssl rand -hex 24) and set it in the profile's cordis.patch.yml (or export DSH_WEBHOOK_SECRET):
- id: dsh-webhook-bridge
name: dsh-webhook-bridge
config:
secret: 'your-shared-secret'
Start dsh, then deliver a message:
curl -X POST http://127.0.0.1:8788/hook/ci \
-H "Authorization: Bearer your-shared-secret" \
-H "Content-Type: application/json" \
-d '{"message": "CI failed on main: run the release pipeline diagnosis"}'
To receive the agent's answer back:
curl -X POST http://127.0.0.1:8788/hook/incident \
-H "Authorization: Bearer your-shared-secret" \
-d '{"message": "Investigate the 5xx spike", "reply_url": "https://your-service.example/hook/agent-reply"}'
All keys live under the dsh-webhook-bridge row's config:
| Key | Type | Default | Meaning |
|---|---|---|---|
host |
string | 127.0.0.1 |
Bind host. Loopback only by default; bind 0.0.0.0 only behind a firewall/proxy. |
port |
number | 8788 |
Bind port. |
secret |
string | env DSH_WEBHOOK_SECRET |
Required in Authorization: Bearer <secret>. Empty = every request rejected. |
provider |
string | — | Provider route for created agents (falls back to profile default). |
model |
string | — | Model for created agents (falls back to profile default). |
cwd |
string | process.cwd() |
Working directory for created agent sessions. |
maxBodyBytes |
number | 1048576 |
Request body limit; larger bodies get 413. |
127.0.0.1 by default. If you bind externally, put it behind a reverse proxy with TLS; the shared secret is the only gate.timingSafeEqual); unauthenticated requests get 401 and never create an agent session.reply_url supplied in the request body, restricted to http:/https:.| Symptom | Cause | Fix |
|---|---|---|
401 on every request |
Wrong/missing Authorization header or empty secret |
Check config.secret and the header spelling (Bearer prefix required) |
413 payload_too_large |
Body over maxBodyBytes |
Raise maxBodyBytes or send smaller payloads |
400 empty_message |
No message/text/content field and empty raw body |
Include one of the recognized fields |
404 not_found |
Wrong path or method | Use POST /hook/<channel>; /health is GET only |
| Replies not arriving | No reply_url supplied for the channel |
Include reply_url; the plugin only calls back when one is set |
| Agent error surfaces in logs | Model/provider failure in the harness | Fix the agent composition; the plugin forwards the request as 500 |
pnpm install
pnpm run typecheck # tsc --noEmit
pnpm run build # tsc → lib/
pnpm run test # vitest: HTTP behavior 200/401/400/413 + extraction helpers
Structure:
src/index.ts — plugin entry (name/inject/Config/apply), session mapping, and createBridge (pure HTTP transport, injectable message handler).tests/ — integration tests start a real server on an ephemeral port and assert the HTTP contract without booting a full harness.Design notes:
createBridge(config, deps) separates transport from agent logic: the HTTP layer is fully unit-testable, and apply supplies the handleMessage callback that creates sessions and forwards messages.node:http and node:crypto cover everything needed here.MIT. Report security issues privately via the repository's security advisory. The bridge executes no agent code itself; all agent behavior is governed by the harness's own permission and sandbox policy.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。