deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:Nono-neko/dsh-browser
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中文
Embedded browser for the DSH Web GUI: browse the web and your workspace files inside the chat interface — multi-tab, address bar, per-workspace tab persistence, page-region review comments, and a lightweight workspace editor — plus agent tools (
browser_open,browser_read,browser_review). Pages are rendered by a headless Chromium (Puppeteer) on the host, so sites that sendX-Frame-Optionsload correctly.
An external plugin package for DeepSeek Harness (DSH). It is a single
dual-face cordis bundle: the host half owns the agent tools, the
/api/dsh-browser route family (Puppeteer page proxy + SSE open-event stream
dsh plugin --profile <name> add link:<repo>.Platform support. Works with both DSH Web and Desktop (requires DSH v0.1.1-rc.1 or later). The visual settings card works out of the box on both platforms — no DSH source changes needed. On Web it appears under Settings → Plugins; on Desktop it appears as a standalone "Embedded browser" entry in the left nav.
A Chromium-based browser must be installed on the host machine (Chrome,
Edge, or Chromium). The plugin auto-detects the executable on Windows, macOS,
and Linux; you can also set an explicit path in the settings card. The plugin
uses puppeteer-core (not puppeteer), so it never downloads its own
Chromium.
networkidle, reads the fully-executed DOM, injects a <base> and a
link-interception script, and returns it to the iframe. Inactive tabs stay
mounted and stateful; iframes lazy-load on first activation. In DSH Desktop,
iframe documents use an isolated loopback preview carrier so Desktop's native
renderer gate does not replace sandboxed subframe responses with forbidden;
Web clients continue using the shared /api/dsh-browser carrier.http(s) links inside a proxied page are
caught and posted to the panel — target="_blank" / window.open opens a
new tab, ordinary links navigate the current tab. Nothing ever pops the
system browser.<base>
injection so relative images/styles resolve, and a CSP sandbox header so a
previewed file can never run scripts in the GUI origin.browser_open pushes a URL into the panel (a new tab opens
and the panel gains focus); browser_read fetches a page from the host and
returns extracted readable text (static-HTML approximation, no JavaScript);
browser_review reads a user-confirmed review batch with page-region coordinates and
browser_review_resolve marks completed comments as resolved.# from a local checkout (development)
dsh plugin --profile <name> add link:<repo>
# from npm (once published)
dsh plugin --profile <name> add @nono-neko/dsh-browser
Restart dsh web; the sidebar entry appears. The web profile needs the
@deepseek-ai/* client packages the bundle injects (any rc.6 web deployment
has them). Make sure a Chromium-based browser is installed on the host.
# remove from a profile
dsh plugin --profile <name> remove @nono-neko/dsh-browser
# if installed from a local checkout
dsh plugin --profile <name> remove link:<repo>
Restart dsh web after removal.
The plugin reads its settings from a layered source: schema defaults, then the
plugin's cordis.yml entry (composition base), then the user settings
document. All fields are optional.
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true |
Mount the sidebar entry, tools, and proxy routes. |
announceToAgent |
boolean | true |
Inject a system-prompt section telling agents about the browser and review tools. |
autoCheckUpdates |
boolean | true |
Check public plugin releases at startup and every six hours. |
followRepositoryUpdates |
boolean | false |
Source installs only: compare the built commit with the repository default branch instead of stable Releases. |
defaultHome |
string | https://www.bing.com |
URL loaded by the new-tab / home button. |
maxTabs |
number | 10 |
Per-workspace tab cap; oldest inactive tab is trimmed. |
allowPrivateAccess |
boolean | false |
Let browser_read fetch private / loopback addresses. |
browserExecutable |
string | auto-detect | Absolute path to a Chromium-based browser (Chrome / Edge / Chromium). |
proxyServer |
string | empty | Route Puppeteer traffic through a proxy, e.g. http://127.0.0.1:7890. |
The plugin provides an interactive settings form out of the box (requires DSH v0.1.1-rc.1 or later):
| Web settings card | Desktop settings page |
|---|---|
![]() |
![]() |
If you prefer not to use the visual settings card, set the same fields directly. Two layers are available:
Plugin entry config (cordis.yml or your profile's plugin config) — the
composition base, applies to every user of that profile:
plugins:
dsh-browser:
defaultHome: https://www.google.com
maxTabs: 20
proxyServer: http://127.0.0.1:7890
User settings document (~/.dsh/settings.yaml) — per-user overrides that
layer on top of the entry config:
dsh-browser:
browserExecutable: C:\Program Files\Google\Chrome\Application\chrome.exe
allowPrivateAccess: true
@nono-neko/dsh-browser on npm and stable Releases in
Nono-neko/dsh-browser on GitHub. npm installations follow the stable version
at the latest tag; source checkouts follow GitHub Releases. A GitHub-only
release is not advertised as installable from npm. Prereleases, equal versions,
and downgrades do not trigger a badge. Unknown installations are labeled and
may display either source; confirm your installation method before updating..git identifies source installs;
a node_modules package identifies npm installs. Other layouts are unknown.
Optional default-branch tracking compares a clean build's commit with the
remote tip and only prompts when that tip is ahead. Dirty/watch builds,
missing revisions, unpublished local commits, and diverged histories cannot
be reliably compared; consult the repository instead. Rebuild and restart the
Host after updating source, then refresh the GUI.proxyServer option.
Save editor contents and local changes before manually updating. No automatic
upgrade, Git operation, or restart is exposed by the update button.Q: Install fails with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED?
A: This happens when installing from git — pnpm blocks the prepare build
script by default. Recommended fix: install from npm instead (pre-built, no
build needed):
dsh plugin --profile <name> add @nono-neko/dsh-browser
If you prefer git install, add the package to allowBuilds in your profile's
pnpm-workspace.yaml:
allowBuilds:
- '@nono-neko/dsh-browser'
For an isolated update-UI smoke check, run pnpm exec vite --host 127.0.0.1
and open /tests/fixtures/update-notifier.html on the printed local URL. The
fixture uses synthetic update responses and a live animated iframe; it does not
contact registries or modify DSH. Verify badges, ignore/restore, failure states,
dark/light themes, modal keyboard behavior, and unchanged preview scroll.
pnpm install # @deepseek-ai/* SDK packages are public on npm (or a mirror)
pnpm build # tsc types + tsdown dual-half bundle (lib/index.js + lib/client.js)
pnpm typecheck # tsc --noEmit
pnpm test # vitest
The build emits two artifacts from one config: the node half (lib/index.js,
esm) and the browser half (lib/client.js, a window.__ModuleLoader__
closure-factory served at /plugins/dsh-browser/client.js). CSS Modules are
compiled into the client bundle by lightningcss; the client bundle enforces a
purity gate — value imports from @deepseek-ai/* are only allowed for the
platform seed modules, everything else must inline or go through cordis
services.
/api/dsh-browser route (proxy, SSE, files,
preview-session negotiation, review screenshots, source editing, reviews,
and update metadata)
refuses non-loopback clients (socket address + Host header + same-origin
markers). A LAN-exposed dsh web cannot serve workspace files or the proxy
to unpaired devices.127.0.0.1 and moves only
iframe GET requests for proxy/file content to a random 256-bit path on that
listener. The capability is process-memory-only, responses use
Referrer-Policy: no-referrer, unknown paths are denied, and the listener is
closed with the plugin routes. It does not expose mutation, SSE, settings, or
other DSH APIs and does not enable Desktop's ordinary-browser access. Workspace
paths still pass through the normal workspace gate and per-preview resource
capability checks.GET /api/dsh-browser/updates reads a cached
snapshot; POST /api/dsh-browser/updates/check requests a rate-limited refresh.
Both enforce the same loopback fence, but need no workspace because they never
read project files. Outbound requests use only fixed HTTPS endpoints at
registry.npmjs.org and api.github.com, refuse redirects, and are capped at
10 seconds and 512 KiB per response. No workspace paths, source contents,
credentials, or comments are sent. The package version is sent as User-Agent;
optional repository tracking also sends the plugin's built commit for comparison.
Release notes are untrusted plain text, not HTML or Agent instructions. Links
are constructed from fixed repository/package URLs, never remote-provided URLs.Content-Security-Policy: sandbox and an opaque iframe origin. The host adds
one response nonce to the page's existing scripts, so local styling and
interactivity still work without granting access to GUI
APIs. Opaque-origin asset GETs require both a browser-classified subresource
destination and a short-lived random capability registered by the initial
same-origin document load; script fetch() and all mutation routes remain
behind the normal same-origin fence. The same capability scopes the live-review
bridge; the parent accepts its messages only from the active iframe with the
matching token, and treats every reported selector, attribute, and rectangle as
untrusted page context.allow-same-origin. Rendered page scripts therefore cannot read the parent
GUI or call its loopback APIs. Review selection and numbered markers for these
proxied pages live in the parent browser surface and do not require DOM access
inside the frame.
Page URLs and all page-derived context are explicitly treated as untrusted,
never as Agent instructions.browser_read: the target hostname is resolved through
DNS before the request leaves the process and every address must be public
(private/loopback/link-local/reserved ranges are refused). Redirects are
followed manually and each hop is re-checked. The allowPrivateAccess
setting is an explicit override; the risk is yours.browser_read does not apply to the panel proxy or review
screenshots. The proxyServer setting lets you route browsing traffic
through a local VPN / proxy. Screenshot viewports are bounded to 1920 by
1080 pixels.browser_read bodies over 2 MB answer an error before
being read; served workspace files over 64 MB are refused; each Puppeteer
render times out after 30 seconds; editor source files are capped at 4 MB.X-Frame-Options.X-Frame-Options on the new URL.
Ordinary <a> links are intercepted and re-proxied.browser_read sees only static HTML: JavaScript-rendered pages come
back without their client-side content, and it cannot use your logins.Apache-2.0
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。