deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:dragonTalon/dsh-browser-assistant
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中文
Let DeepSeek Harness (dsh) read and operate the browser tab you already have open — pages become text-only structured snapshots, the model addresses elements by number, and your login state, session, and cookies stay intact.
One pnpm workspace, two halves joined by one WebSocket:
packages/bridge-dsh — the dsh Cordis plugin, released as bridge-dsh 0.2.0, that mounts /ext/bridge and registers 12 browser_* tools.packages/extension — the Chrome MV3 extension, released as bridge-browser 0.2.0 (service worker + content script + side panel).The model tool pipeline is text-only — pages become structured text snapshots, tools never capture screenshots. Separately, a user-initiated drag-select in the panel can send a cropped region screenshot to a vision-capable model. See docs/en/architecture.md for the full design.
| Capability | How |
|---|---|
| Read page | browser_snapshot → title/URL/main text/numbered controls/forms; delta:true returns only changes |
| Operate | browser_click / browser_type / browser_press / browser_scroll by stable number |
| Navigate | browser_navigate / browser_open_tab / browser_back / browser_forward / browser_reload |
| Read region / wait | browser_get_text / browser_wait |
| Ask the user | dsh ask_user_question renders in the panel; answers flow back to the model |
| Page awareness | extension tracks the active tab and injects its URL/title into each prompt as context |
| Region capture | user drag-selects a page region → cropped screenshot + DOM element list → sent to a vision-capable model |
| Model selection | panel re-pulls model.catalog on connect; dropdown with capability badge (vision / text / unknown) → session.selectModel |
| Session picker | dropdown over session.list, "new session" by default; a session is created on the first send, on the first model pick, or when the / menu is opened from "new session". Picking a past session binds it and replays its history — no orphans, no session.create |
| Slash commands & skills | / opens a filtered, keyboard-navigable menu over the bound session's host commands and user-invocable skills: a command runs through commands.execute (whole line, arguments included), a skill is sent as an ordinary prompt, and the command/run/command/done pair renders its lifecycle in the conversation |
| Session grouping | with sessionWorkspace configured, extension-created sessions join that dsh Workspace — grouped under the directory in the dsh sidebar instead of piling up in "Ungrouped" |
Security model: the bridge carries its own bearer token; reads are auto-allowed, state-changing actions fail closed behind a side-panel approval; passwords/card numbers are masked and never leave the page. A remote connection requires the token and relaxes none of the above.
^22 and Corepack/pnpm0.1.2-rc.1 — the minimum supported version (the 0.1.x Typert Gateway + Connection architecture); verified against 0.1.3-alpha.1The bridge plugin is published to npm; the Chrome extension ships as a pre-built zip on GitHub Releases. No local compilation needed.
dsh plugin --profile web add -w "bridge-dsh@0.2.0" --config.minimumReleaseAge=0
Pin the version — do not use
@latest. Since pnpm 11,minimumReleaseAgedefaults to1440minutes (1 day): a version published less than a day ago is held back, and a dist-tag like@latestsilently resolves to the previous version instead of failing.--config.minimumReleaseAge=0lifts that wait for this one install. The bridge plugin and the extension are a versioned pair, so always install the version that matches yourbridge-browserzip.
gh release download bridge-browser@0.2.0 --repo dragonTalon/dsh-browser-assistant
# → bridge-browser-0.2.0.zip
cd ~/.dsh && dsh web
curl http://127.0.0.1:3080/ext/bridge-config
# → {"wsUrl":"ws://127.0.0.1:3080/ext/bridge"}
Unzip bridge-browser-0.2.0.zip, then chrome://extensions → enable Developer mode → Load unpacked → select the unzipped folder. Open any http(s) page, click the extension icon to open the side panel, wait for 已连接 dsh, and chat.
If dsh runs on another machine, open the panel's System config (gear button in the status bar), enter the address (10.0.0.7:3080 or wss://dsh.example.com) and the token from that machine (cat ~/.dsh/ext-bridge-token), then press Test connection before saving — it performs one isolated handshake and tells you whether the address is unreachable or the token was rejected. Leaving the address empty keeps the zero-config local discovery.
Methods pinned to loopback (settings.*, credentials.*, host.openPath, host.pickDirectory) stay unavailable over a remote connection — that is the bridge's own trust fence, not a bug in the dialog.
pnpm install --frozen-lockfile
pnpm build
# → packages/bridge-dsh/lib/index.js and packages/extension/dist/
Note for local development: dsh plugin add installs a packed snapshot (~/.dsh/profiles/<profile>/node_modules/bridge-dsh/), so rebuilding the workspace lib/index.js alone never reaches the running dsh. After every bridge source change:
bash packages/bridge-dsh/build.sh # rebuild the workspace artifact
bash scripts/sync-profile.sh # copy into the installed plugin dir (auto-backup)
# then restart dsh (or reload the plugin) so the new bundle is loaded
The copy above replaces the profile's file, but the running dsh keeps the module it already imported. A live patch reload re-runs the plugin's
apply()with the new config while still using the old module, so a source change always needs a dsh restart.
pnpm test # the release gate: typecheck + ALL offline checks (scripts/run-tests.mjs)
pnpm test:e2e # the two live checks in one command; needs a running dsh
pnpm check:slash # 28 offline assertions for the slash vocabulary + catalog lifecycle
pnpm check:ordered-rpc # 7 assertions driving a real BridgeServer over a real WebSocket:
# the ordered-RPC bound releases the queue slot instead of hanging the session
pnpm check:grouping-lifecycle # 6 assertions: workspace registration survives a connection replacement
pnpm check:selection # 32 offline assertions for the session picker (buffers, seq, history replay)
pnpm check:grouping # 24 offline assertions for the sessionWorkspace contract + its diagnostic trace + plugin wiring
pnpm check:permission # 43 offline assertions for the permission-tier rules + spec-scenario coverage classification
pnpm check:grouping:status # read-only triage (no dsh needed): registry membership vs the directory's real Session files
pnpm check:selection:e2e # live end-to-end: session selection against a running dsh
pnpm check:grouping:e2e # live end-to-end: session.create over the real bridge, asserted from the Workspace registry
The offline checks need no dsh, no Chrome and no network — they bundle the real sources with esbuild and assert the spec scenarios in Node; pnpm test runs them all (plus typecheck) through scripts/run-tests.mjs, and is the gate every release must pass. The bridge's own typecheck needs the dsh host framework's types (@deepseek-ai/*), which live in a local dsh installation: after checkout run bash scripts/link-dsh-types.sh once to link them into the package. check:grouping:status reads only the on-disk registry and Session store, and answers "why did this conversation not land in the group?"; the two :e2e checks need a running dsh (check:grouping:e2e additionally needs sessionWorkspace configured); they briefly supersede the Chrome panel's bridge connection (the bridge serves one at a time; the extension reconnects on its own) and create a real Session on every run.
The two halves are released independently:
| Artifact | Package | Version | Git tag |
|---|---|---|---|
| dsh bridge plugin | bridge-dsh |
0.3.0 |
bridge-dsh@0.3.0 |
| Chrome extension | bridge-browser |
0.3.0 |
bridge-browser@0.3.0 |
Tagging is done through the release gate, which refuses to tag unless the full offline suite passes:
bash scripts/tag-release.sh bridge-dsh 0.3.0 # typecheck + pnpm test, then tags and pushes
bash scripts/tag-release.sh bridge-browser 0.3.0 --e2e # additionally runs the live checks (needs a running dsh)
The script verifies the version against the package's package.json (and the extension's manifest.json), runs the gate, then creates and pushes the tag; any failure aborts without a tag. The pushed tag triggers the pipeline below, which runs the same offline suite once more before building.
The bridge plugin is on npm: bridge-dsh. Each tag also has a matching GitHub Release with its built artifact, produced automatically by the tag-triggered pipeline (.github/workflows/release.yml):
bridge-dsh — install from npm: dsh plugin --profile web add -w "bridge-dsh@0.3.0" --config.minimumReleaseAge=0 (a bridge-dsh-0.3.0.tgz is also attached to its release)bridge-browser-0.3.0.zip — the extension bundle; load it via chrome://extensions → Load unpacked (or submit to the Chrome Web Store)Every release description is bilingual and is generated from that package's changelog, so the notes can never drift from what shipped: packages/bridge-dsh/CHANGELOG.md · packages/extension/CHANGELOG.md.
packages/protocol/ shared zero-dependency wire protocol (single source of truth)
packages/bridge-dsh/ dsh bridge plugin (Cordis)
packages/extension/ Chrome MV3 extension (background / content / panel)
docs/en/ docs/zh/ architecture & feature docs (EN / 中文)
Documentation is bilingual — every page has an EN | 中文 switcher:
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。