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
A DeepSeek Harness plugin that shares the current session page as a long screenshot — a single PNG of the whole conversation, not just the visible viewport.
Adds a copy button to the session header (top-right, next to the jobs / subagent buttons). Click it and the browser captures the full conversation — every loaded message — and copies it to the system clipboard as a PNG. Paste it anywhere: a chat, a document, an image editor.
The page is painted by the browser's own layout engine into an SVG foreignObject (via modern-screenshot, bundled inline), so the result matches what you see: CSS variables, gradients, web fonts, and emoji render correctly. Dark themes keep their real background. Output is 2× device pixels (clamped to browser canvas limits for very long sessions).
The capture is auto-cropped: the conversation column is capped (max-width: 748px) inside a wide container, so a full-container capture carries ~200px of empty gutter on each side. A downscaled probe finds the content bounding box and the final image is trimmed to the content plus a small margin. The composer (input box) is excluded — it is full-width chrome that would otherwise keep the crop wide; the share is the conversation itself.
Clipboard copy uses navigator.clipboard.write with a ClipboardItem (Chrome / Edge / Safari), with an <img>-selection execCommand('copy') fallback for browsers without image clipboard support.
The plugin is a dual-half dsh plugin:
| Half | File | Role |
|---|---|---|
| Host | index.js |
Trivial loader entry — the package must be an active loader entry for the client bundle to be composed |
| Browser | client.js |
apply() registers a component into the conversation.session.header.actions slot; the button captures and copies |
The browser bundle follows the dsh client-module artifact format: a closure factory handed to window.__ModuleLoader__.load({ id, factory }), resolving platform modules (react, @deepseek-ai/*) through the loader's module table and inlining everything else.
Install straight from GitHub — the built halves (index.js, client.js) are committed, so no build step is needed:
# 1. install the package into your profile
cd ~/.dsh/profiles/web
pnpm add -w "dsh-share@github:coder-wu/dsh-share"
# or, with an explicit git URL:
# pnpm add -w "dsh-share@git+ssh://git@github.com/coder-wu/dsh-share.git"
# 2. restart dsh web (dsh plugin add reconciles dsh.profile.bundles automatically)
Switching an existing link: install to the GitHub source: pnpm remove -w dsh-share first, then add from GitHub as above.
cordis.patch.yml inserts the loader row { id: share, name: dsh-share }; the dsh.client declaration in package.json makes the client-modules service serve ./client.js to the web shell.
# 1. remove the package from your profile (also drops it from dsh.profile.bundles)
cd ~/.dsh/profiles/web
pnpm remove -w dsh-share
# or, via the dsh CLI:
# dsh plugin --profile web remove dsh-share
# 2. restart dsh web
The button disappears from the session header once the server restarts; no other cleanup is needed — nothing is stored in the profile beyond the dependency entry.
npm install # esbuild + modern-screenshot (build-time only)
npm run build # emit index.js + client.js
npm run watch # rebuild on change; dsh client HMR hot-reloads the plugin
localhost qualifies. If the page lacks clipboard permission the legacy image-copy path is used, and a failure surfaces as a toast.CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。