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
Home Assistant control for DeepSeek Harness agents.
Read entity states · query history · call services — every state-changing call sits behind a human approval gate.
中文 ·
·
·
Zero runtime dependencies beyond the harness itself. Uses Home Assistant's built-in REST API — no MQTT, no WebSocket, no extra daemon.
Click any image to open the live demo — docs/demo.html simulates the full DSH conversation, and its live console talks to the bundled HA emulator (no real Home Assistant needed).
| ① Ask | ② Approval gate | ③ Done — state changed |
|---|---|---|
![]() |
![]() |
![]() |
The agent lists your lights with ha_list_entities. |
ha_call_service pauses for a human approval dialog. |
Approved — ha_get_state confirms the light turned on. |
And the Web UI dashboard card — call ha_dashboard and get a live snapshot of the whole home rendered right in the conversation:

The Home Assistant it plugs into — a typical smart-home dashboard like this one (illustration):

Talk to your home the way you talk to an assistant — every write goes through a human approval gate first.
| You say | What happens |
|---|---|
| "Check the whole house — which devices are still on?" | Agent scans with ha_list_entities / ha_get_state and summarizes |
| "Show me the home dashboard." | ha_dashboard renders a live dashboard card in the conversation — devices, scenes and recent changes at a glance |
| "Set the bedroom light to 200 brightness." | ha_call_service → approval dialog → executes → state updates instantly |
| "Turn off every light in the living room." | Area targeting — one call controls the whole room |
| "Start cinema mode." | Scene activation: dimmed lights + TV on — a whole cascade of devices in one shot (ha_events shows each change live) |
| "What changed in the house in the last hour?" | Real-time state_changed events from the WebSocket feed |
| "Is the living room warm enough? Compare with the bedroom." | ha_get_state / ha_render_template over sensors |
| "Turn everything off, I'm leaving." | One scene (scene.away) or a multi-entity service call |
dsh plugin --profile web add dsh-smarthome, then just talk to the agent.allowedDomains is a second deny-list belt. The agent can never touch your home without you saying yes.dsh-smarthome runs right where dsh runs — on your computer. No phone app, no separate bridge, no context switch:
ha_dashboard) and the real-time event feed (ha_events) keep the whole house visible next to your editor: what's on, what just changed.dsh-plugin topic for voice; e.g. dsh-voice does zero-key speech input + read-aloud, dsh-voice-chat does real-time speech) and just speak: "turn the bedroom light to 200" → approval → done. Hands-free while you keep typing.| Tool | Description | Approval |
|---|---|---|
ha_health |
Verify the connection; return instance name, version, timezone, WebSocket status | read |
ha_list_entities |
List entities, filter by domain (light, switch, sensor…) and text |
read |
ha_list_areas |
List rooms (areas) via the WebSocket API, e.g. living_room |
read |
ha_list_devices |
List physical devices via the WebSocket device registry | read |
ha_get_state |
Full state + attributes of one entity | read |
ha_history |
State-change timeline over a time window | read |
ha_events |
Recent real-time state changes buffered from the WebSocket | read |
ha_list_scenes |
List one-click scenes (cinema, goodnight, away…) |
read |
ha_dashboard |
Full home snapshot rendered as a dashboard card in the Web UI | read |
ha_call_service |
Call any service — by entity, by area (whole room), by device, or scene | ask |
ha_render_template |
Render a Jinja2 template server-side | ask |
Example prompts:
"Check that Home Assistant is reachable, then list the lights in the living room."
"Set the living room light to 60% brightness." (triggers an approval request)
"Show me the boiler switch history for the last 24 hours."
"Turn off every light in the bedroom." (area targeting — one call, whole room)
"Start cinema mode." (scene activation — lights dim, TV turns on)
"What changed in the house in the last hour?" (real-time
ha_events)
Requires dsh ≥ 0.1.0-rc.6 (current npm latest).
# From npm (recommended — prebuilt):
dsh plugin --profile web add dsh-smarthome
# Or from GitHub (source install — pnpm builds on the fly):
# dsh plugin --profile web add github:YLifeOnlyOnce/dsh-smarthome
# If pnpm refuses to run the prepare build on a git dependency, allow it once:
# add this to <profile>/pnpm-workspace.yaml, then re-run the add:
# allowBuilds:
# dsh-smarthome: true
Restart dsh --profile web after installing. Manage it in Settings → Plugins.
No HA instance? The repo ships a fake HA emulator with a small living demo home whose state actually changes when you call services — perfect for trying the plugin before wiring up real hardware.
git clone https://github.com/YLifeOnlyOnce/dsh-smarthome
cd dsh-smarthome
pnpm install
pnpm demo:ha # serves a fake Home Assistant at http://127.0.0.1:8124
In another terminal, configure the plugin (add to your profile's cordis.patch.yml):
- id: smarthome
config:
baseUrl: http://127.0.0.1:8124
tokenEnv: HOME_ASSISTANT_TOKEN
Then start dsh and try:
HOME_ASSISTANT_TOKEN=demo-token dsh --profile web
"Check that Home Assistant is reachable, then list the lights."
"Turn on the bedroom light at 200 brightness." — an approval request pops up; approve it, and
ha_get_statewill show the light is actuallyonwithbrightness: 200."Turn off every light in the living room." — area targeting via the WebSocket area registry.
"What changed in the last minute?" — real-time
state_changedevents from the WebSocket feed.
The emulator also drifts the temperature sensor every few seconds, so ha_history and ha_events always have fresh data. Any Bearer token works; demo-token is just the convention.
Want to preview the UI without running dsh at all? Open docs/demo.html in a browser: it replays a simulated DSH conversation (tool cards + the approval dialog), and its live console talks to the emulator directly when it's running.
Ready-to-paste configs (demo / real HA / no-approval) live in examples/cordis.patch.yml.
Create a long-lived access token in Home Assistant: Profile → Security → Long-lived access tokens.
Override the plugin row in your profile's cordis.patch.yml (later layers win):
- id: smarthome
config:
baseUrl: http://192.168.1.10:8123 # your Home Assistant instance
token: '' # prefer tokenEnv over committing a token
tokenEnv: HOME_ASSISTANT_TOKEN # env var holding the token
timeoutMs: 15000
requireApproval: true # human approval for state-changing calls
allowedDomains: [] # e.g. ["light", "switch"]; empty = all domains
maxHistoryEvents: 200
wsEnabled: true # real-time events + area registry (WebSocket)
eventBufferSize: 50 # rolling ha_events buffer size
Then run dsh with the variable set:
HOME_ASSISTANT_TOKEN=<token> dsh --profile web
baseUrl defaults to http://homeassistant.local:8123 (the standard Home Assistant mDNS host). If no token is configured the plugin still loads — every tool call fails with a clear "not configured" message instead of crashing the harness.
tokenEnv is a credential reference resolved through the harness's credential seam: when the credentials service is present, the value is read from its layered sources (process environment → <cwd>/.env → $DSH_HOME/.env), falling back to process.env directly otherwise. The token is re-resolved per request / per socket connection, so a rotated credential reaches the very next call without a restart.
requireApproval defaults to true and ha_call_service / ha_render_template always route through the harness approval seam.allowedDomains is a second belt: when set, service calls on other domains are denied outright.tokenEnv over token so the secret never lands in a committed config file.pnpm install
pnpm typecheck # strict TS against the published @deepseek-ai/* types
pnpm build # bundle lib/ (ESM + d.ts)
pnpm test # 24 tests: client suite + real ToolRuntime integration + full agent-loop E2E
node scripts/capture-demo.mjs # regenerate the README screenshots
/api/states, /api/services/…, /api/history/…, /api/template, /api/config) and the WebSocket API (/api/websocket: auth, subscribe_events, config/area_registry/list, config/device_registry/list) — the same protocols the official HA frontend speaks.http:// or a valid cert); a restricted token that cannot call services will fail ha_call_service.DeepSeek Harness is in developer preview and changes fast. This plugin is verified against the published @deepseek-ai/dsh@0.1.0-rc.6 line; if a harness update breaks it, please open an issue.
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。