DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Embedded Browser — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

dsh-embedded-browser

Embedded Browser

一个运行在 DSH 主机内的浏览器:每个会话都有自己的标签页,AI 通过按需发布的 browser_embedded_* 工具驱动它,人类可在按需显示的右侧 Sidebar 标签页中查看或接管同一个标签页——无需 GUI、无需外部浏览器,并支持登录、2FA、二维码和 CAPTCHA。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-embedded-browser@0.3.0
README兼容性版本

兼容性与来源证明

Embedded Browser 以 dsh-embedded-browser 发布,当前版本为 0.3.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/9/21

版本

0.3.0stable
2026/9/21

相关插件

正在加载相关插件…

最新版
0.3.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 0
周下载
0
最近提交
2026/9/23
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

README

dsh-embedded-browser

English | 简体中文

A browser that lives inside the DSH host: every DSH session gets its own tab in it, the AI drives that tab with browser_embedded_* tools, and you watch — or take over — the very same tab in a right-sidebar tab that opens on demand in the DSH Web UI.

Renamed in 0.3.0. Up to 0.2.0 this plugin was dsh-browser-panel: its tools were browser_panel_*, its routes lived under /api/dsh-browser-panel/*, and its profile under $DSH_HOME/browser-panel/profile. The package, the repository and every one of those names changed together, so the tool prefix now matches the package name. Point profileDir at the old directory if you want to keep the logins of an 0.2.0 install.

It exists for one stubborn problem: agents run on machines with no display, but the sites they need are behind a login. A headless browser can be scripted; it cannot scan a QR code, type an SMS code, or solve a CAPTCHA. With this plugin the human does that part inside the DSH Web UI, on the same tab the AI is already working on, and the result stays in a persistent profile — so a login performed once works in every session, now and after a restart.

The problem

  • An agent host (container, VM, CI box) has no GUI, so it cannot show you a login page.
  • Fully headless automation breaks at the first step that needs a person: SSO redirects, one-time passcodes, QR-code logins, CAPTCHAs, hardware keys.
  • Copying cookies or storageState into the container is fragile: device-bound credentials, fingerprints, and WebAuthn simply do not transfer.

What it does

One browser, one tab per session, two control planes. The AI speaks CDP on its own tab; the human sees and drives that same tab from the sidebar tab that mirrors it. The login the human performs is exactly the session the AI keeps using — and because all sessions share one profile, every other session is logged in too.

Tools (published lazily)

The ten browser_embedded_* tools are not registered when the plugin loads. Their schemas are billed on every request, so by default they stay off the tool list until something proves the model is doing browser work:

  • a successful skill call naming browser-use;
  • the /browser-use gesture typed by a human;
  • a past successful invocation found in a session log — this third path is what reopens the gate after a plugin reload.

So: no skill, no tools. Install the browser-use skill alongside this plugin (see Install) — it is the routing skill that also covers the BrowserSkill channel, and calling it is what publishes these ten. Once open, the gate stays open for the whole host process and for every session, because ctx.tools.register writes into one host-wide registry. Set lazyTools: false to register the suite at load instead.

CapabilityToolNotes
Report statebrowser_embedded_statusRunning? Which URL/title has this session's tab? Is a human action pending?
Open a URLbrowser_embedded_navigateStarts the browser on first use; newTab replaces this session's page with a fresh tab
Read the pagebrowser_embedded_snapshotTitle, URL, numbered inventory of clickable/typable elements, visible text
Clickbrowser_embedded_clickBy element number or by visible text; real input events
Fill a fieldbrowser_embedded_typeReact/Vue-friendly insertion; submit presses Enter
Press a keybrowser_embedded_pressEnter, Tab, Escape, arrows, PageUp/Down, …
Scrollbrowser_embedded_scrolldown/up/left/right/top/bottom
Look at the pagebrowser_embedded_screenshotPNG returned to the model as an image attachment
Ask the humanbrowser_embedded_ask_humanBrings up this session's browser tab with your instruction and waits until they press 我已完成
Close the tabbrowser_embedded_closeCloses this session's tab; the profile (and every login) stays

Sidebar side (DSH Web UI):

  • a 浏览器 / Browser tab in the right sidebar holds the live view of that session's tab. It is not pinned to every session: it opens itself the moment the session gets a browser tab, so a conversation that never touches a browser shows no extra surface at all;
  • the right sidebar's guide page carries an 内嵌浏览器 / Embedded browser entry, which is how you open the tab by hand (before the AI has started a browser, or after you closed it);
  • the tab chip carries a small dot while the session it belongs to is waiting for a person — the only cross-session signal now that the host-wide overview is gone;
  • the canvas accepts your mouse, wheel, keyboard and IME input — it is not a screenshot viewer, the events are replayed into the very CDP session the AI uses;
  • the hand-over banner appears in the tab of the session that asked, with a 我已完成 / Done button that resumes the waiting tool call (and an optional note back to the AI);
  • a toolbar with back / forward / reload / repaint, Tab / ⇧Tab / Enter to walk a form without aiming the mouse, and 结束并清理 / Close tab;
  • closing the tab is obeyed: it does not come back by itself until the browser itself comes back — except for a new hand-over request, which would otherwise hang until it timed out.

How it works

flowchart LR
  AI["AI turn<br/>(browser_embedded_* tools)"] -->|"CDP · this session's tab"| B["Chrome<br/>(persistent profile)"]
  H["You, in the DSH Web UI"] -->|"mouse · keyboard · IME"| P["Right-sidebar tab<br/>(client half)"]
  P -->|"WebSocket /api/dsh-embedded-browser/stream?session=…"| S["Host half<br/>(screencast + input replay)"]
  P -->|"GET /api/dsh-embedded-browser/sessions (2 s poll)"| S
  S -->|"Page.startScreencast (the visible tab)"| B
  S -->|"Page.captureScreenshot (~7 fps, the rest)"| B
  S -->|"Input.dispatch* (that tab)"| B
  B -->|"JPEG frames"| S --> P
  B -.->|"one profile: cookies, localStorage"| D[("profile dir<br/>$DSH_HOME/embedded-browser/profile")]
  • The host half launches one Chrome per DSH host process. With mode: auto it runs headed on a private Xvfb when Xvfb is available (better fingerprint than headless) and falls back to --headless=new otherwise.
  • A session's tab is created lazily — on that session's first browser_embedded_* call, or when the human presses the open button in that session's sidebar tab — and closed when the session is disposed, when the AI calls browser_embedded_close, or when the human presses 结束并清理 / Close tab. Sessions are isolated in page state, not in identity: they share the profile, so a login performed once is available everywhere.
  • Every tab is activated once when it is created. A Chrome target that was never activated silently discards every injected input event for the rest of its life, and one activation repairs it permanently. Afterwards a session's tab accepts input even while it is in the background — so the AI never moves your foreground.
  • Chrome only emits screencast frames for the active tab. The sidebar tab you are actually looking at sends focus and owns the real Page.startScreencast; every other attached session is served by polled Page.captureScreenshot frames (~7 fps target; its first frame can be cold — seconds — while another tab owns the screencast). A freshly opened panel always gets a seeded frame, because a static page emits none on its own.
  • The tab body is mounted while its tab is invisible too (a collapsed column, an inactive tab), so the component gates on visibility rather than on mount: a hidden tab holds no WebSocket and asks for no focus, and therefore never steals the browser's foreground from whoever is watching.
  • Tools carry no session parameter: every handler reads the session id from its own execution context (exec.agent.id), so tool names and parameters stay small and a session can never steer another session's tab. A call with no owning session is an error.
  • The tools are published by the routing skill rather than by plugin load (see above); the plugin's own system-prompt section points the model at that skill, which is what keeps a gated suite discoverable.
  • The panel is served by the host webserver, on the same origin and behind the same session authentication as the Web UI itself (connection.requestRejection). The routes that belong to a session carry its id — GET /api/dsh-embedded-browser/state?session=…, POST /open|/close (session in the body), and the /stream?session=… WebSocket upgrade — while GET /sessions and GET /health describe the whole host, and settles a request by id. No extra port, no extra token, no tunnel.

Requirements

  • DSH >= 0.1.5-rc.2, Node >= 22.19.
  • A Chromium-family browser. Auto-detected in this order: browserPath config → google-chrome-stable / google-chrome / chromium / chromium-browser / chrome on PATH → Playwright cache (~/.cache/ms-playwright/chromium-*/…) → Puppeteer cache.
  • Optional: Xvfb on PATH for headed mode. Without it the plugin runs headless automatically.

Install

Version 0.3.0. This release renames the package, so it breaks every name an 0.2.0 install used: dsh-browser-panel → dsh-embedded-browser, browser_panel_* → browser_embedded_*, /api/dsh-browser-panel/* → /api/dsh-embedded-browser/*, $DSH_HOME/browser-panel/profile → $DSH_HOME/embedded-browser/profile. 0.2.0 is the last release under the old name; 0.2.0's own break (per-session tabs, no shared-page mode) still stands.

# npm
dsh plugin --profile web add dsh-embedded-browser

# straight from GitHub
dsh plugin --profile web add github:imroc/dsh-embedded-browser

A plugin has to end up in the profile twice: as a dependency (so its code is in the profile's own node_modules) and in dsh.profile.bundles (so the patch that inserts the plugin row is actually applied). dsh plugin … add does both, because the package declares dsh.bundle; a dependency added by hand alone mounts nothing.

The package ships its built JavaScript, so nothing is compiled on install.

Restart the Web UI afterwards (adding a plugin row is a boot-time composition change):

systemctl --user restart dsh-web      # or however you run `dsh web`

Recommended: the browser-use skill

The ten tools are gated behind the browser-use skill, and that skill does not ship inside this package — it belongs to the skills your profile loads. Without it (or a /browser-use gesture) the gate never opens and no browser_embedded_* tool is ever published; the model will simply report that those tools do not exist:

  • install a global browser-use skill, or
  • set lazyTools: false to register the suite at load, and pay its schemas on every request.

The skill name is compiled into lib/lazy.js (SKILL_NAME). If you rename the skill on your side, rename it there too.

Verify

  1. The tools are gated, so open the gate first: ask the AI to use the browser-use skill, or type /browser-use in the conversation. The ten browser_embedded_* tools are now published for every session in this host process.

  2. Ask for a page:

    Use browser_embedded_navigate to open https://example.com, then browser_embedded_snapshot.
    
  3. The first browser call opens a 浏览器 / Browser tab in the right sidebar by itself — that is this session's own tab in the host Chrome. Before there is any browser there is no tab; the sidebar's guide page (内嵌浏览器 / Embedded browser) is the manual way to open one first.

  4. Ask the AI to hand over, then complete the login yourself in that tab:

    Call browser_embedded_ask_human with the instruction "请在面板里完成登录,然后点我已完成".
    
  5. Log in, press 我已完成 — the tool call returns, and the AI continues with an authenticated session. Close the tab first if you like: the next hand-over request brings it back.

  6. In a second session, open its own browser tab: it is a different tab, but it is already logged in, because the profile is shared. Close one session's tab (browser_embedded_close, or 结束并清理 / Close tab) and reopen it: still logged in.

Configuration

Override any field from your own patch layer (~/.dsh/cordis.patch.yml, or the profile's cordis.patch.yml). The whole config key is replaced, so restate what you need:

- id: embedded-browser
  config:
    mode: headless            # auto | headed | headless
    viewport: 1280x800
    idleShutdownMinutes: 30
KeyDefaultMeaning
browserPath''Explicit Chrome/Chromium path; empty = auto-detect.
profileDir''Persistent profile; empty = $DSH_HOME/embedded-browser/profile. Shared by every session.
modeautoauto = headed on a private Xvfb when available, else headless.
screen1440x900x24Geometry of the private Xvfb.
windowSize1440x900Chrome window size in headed mode.
viewport1440x900Emulated page viewport — the same for every session tab, and the sidebar canvas coordinate space.
xvfbDisplay:99Preferred X display; the next free one is used if taken.
port0Fixed DevTools port; 0 picks a free one.
startUrlabout:blankFirst URL of each session's fresh tab.
extraArgs[]Extra Chrome switches.
snapshotMaxChars4000Page text budget per snapshot.
maxElements80Interactive elements listed per snapshot.
screencastQuality60JPEG quality of the stream (and of the polled stills).
screencastMaxWidth1440Maximum streamed frame width.
pollFrameMs140Poll interval for panels that cannot own the foreground screencast (~7 fps). Values below 60 are clamped.
askHumanTimeoutSeconds600

Security notes

  • The panel and its WebSocket live behind the same authentication as the DSH Web UI. Anyone who can see the panel can already drive the host browser — treat Web UI access accordingly.
  • Sessions are isolated in page state, not in identity: every session uses the same browser profile, and therefore the same cookies and logins. That is the point of the plugin, but it also means one session's AI can reach any site the profile is logged into.
  • The browser profile holds real sessions. It stays on the host, under the DSH home, is never uploaded, and is not part of the Git repository.
  • Browser traffic goes out from the container. A data-centre IP is a weaker signal than your laptop's; for sites that are aggressive about automation, mode: headed (the default whenever Xvfb is available) is the better half of the trade.
  • Prefer running Chrome as a non-root user with the sandbox on; the plugin only adds --no-sandbox automatically when the host process runs as root.

Rollback

dsh plugin --profile web remove dsh-embedded-browser   # or delete the row from cordis.patch.yml

Then restart the Web UI. The profile directory is left in place, so reinstalling keeps your logins. Delete $DSH_HOME/embedded-browser/profile to forget them.

License

MIT

POST /human-done
  • Human take-over is per session: two sessions can wait on a human at the same time, and a request is delivered only to the sidebar tab of its own session.
  • Frames travel as JPEG over one WebSocket; input travels back as small JSON messages. Frames are dropped rather than queued when your connection falls behind.
  • Nothing is written into DSH core: the plugin is one composition row.
  • The measured constraints behind these choices are written down in references/PITFALLS.md (#11–#13 for the browser, #14–#16 for the sidebar and the lazy gate).
  • Default budget of browser_embedded_ask_human.
    idleShutdownMinutes10Stop the browser — and with it every session's tab — after this much idle time; 0 never stops it. Reaping is lossless: a tab reopens at its last URL, and the profile keeps every login.
    autoStartfalseStart the browser with the host instead of on first use.
    lazyToolstruePublish the ten tools only after the browser-use skill is invoked; false registers the suite at load.
    startTimeoutMs20000How long to wait for the DevTools endpoint after launch.

    相关插件

    继续浏览 search-research 分类下经过校验的插件。

    Weknora@wxg-prc-cpg/dsh-weknora适用于 DeepSeek Harness (dsh) 的 WeKnora 知识检索工具:通过自有知识库进行语义搜索、文档阅读以及 RAG/代理回答。Find Plugindsh-find-plugin在代理中查找 DeepSeek Harness 插件——实时搜索 GitHub 上的 dsh-plugin 主题,并按星标数排序。Builtin Browserdsh-builtin-browserDeepSeek Harness 的共享真实浏览器插件:安装即用——可由人类接管的可见原生浏览器,由代理通过 CDP 驱动。支持 DOM 级交互(React/Vue 安全)、按任务隔离会话、Cookie 持久化(browser_auth)、CAPTCBrowser@anweat/dsh-browserDeepSeek Harness 的自包含浏览器运行时插件(作用域为 @anweat)——将 Playwright(chromium)和 OpenCLI 作为插件本地依赖进行打包(支持全局复用回退),提供 `browser` 服务和交互式浏览器工具。