dsh-browser-playwright-codex

DSH PLUGIN浏览器与联网

仓库 miqian-nomad/dsh-browser-playwright-codex · npm dsh-browser-playwright-codex

浏览器与联网 L5 · 运行验证通过 安全审查:低风险 可信度:金 可安装插件
安装这个插件

为 DeepSeek Harness 提供 Playwright 浏览器自动化能力,整合 Codex 风格点击与 CDP 策略,并修复最小化窗口被拽回桌面的问题。

一句话选型结论

按资料字段整理

dsh-browser-playwright-codex 是浏览器与联网类的 DSH 可安装插件,验证等级 L5 · 运行验证通过,安全审查为低风险,列出 5 项功能,有可直接复制的安装命令。验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么;涉及密钥或系统权限的,建议先在隔离环境试装。

分类浏览器与联网 收录类型可安装插件 验证等级L5 · 运行验证通过 安全审查低风险
验证等级 L5 L5 · 运行验证通过
GitHub 星标 1 复刻 0 · 未关闭 issue 2
最近更新 2026-10-06 创建于 2026-09-26
README 30.0 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
dsh plugin --profile web add dsh-browser-playwright-codex@0.5.3
  1. 1
    确认版本与运行环境

    兼容的 DSH 版本为 0.2.0-rc.2 等 3 个,Node.js 要求 ^22.19.0 || >=24.0.0;版本不匹配时安装会报错。

  2. 2
    执行安装命令

    在 DSH 里执行上面的命令;多包仓库要注意区分具体子包名,别装错包。

  3. 3
    确认已挂载

    用 dsh plugin list 查看列表里是否出现这个插件,出现即挂载成功。

  4. 4
    试跑并检查权限

    加载后跑一个最小用例,确认它能正常工作;同时看它申请了哪些文件、命令或网络权限。

兼容 DSH 版本0.2.0-rc.2 等 3 个版本版本不匹配时安装会报错
Node.js 要求^22.19.0 || >=24.0.0来自仓库 package.json 的 engines 字段
前置依赖@deepseek-ai/cordis@*、@deepseek-ai/dsh-llm@* 等 3 个需要同时安装的同级依赖
npm 包名dsh-browser-playwright-codex可用 npm view 查看包信息

能做什么

5 项功能
字段来自项目仓库与公开索引,中文说明由本站标注

dsh-browser-playwright-codex:为 DeepSeek Harness 接入真实浏览器操作

  • Playwright 有头浏览器自动化
  • 无障碍快照与元素交互
  • 几何点击与 CDP 策略层
  • 持久化 profile 与登录态导出
  • 修复最小化窗口被拽回

适用场景

联网搜索

上游标签

ai-agentautomationbrowserbrowser-automationcodexdeepseekdeepseek-harnessdshdsh-pluginform-fillingheadfulplaywrightrpaweb-automationweb-scraping

验证等级与安全审查

L5 · 运行验证通过
自动化流程结论,不是人工审核
验证等级L5 · 运行验证通过在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来
安全审查低风险静态分析结论,未标注不代表已通过审查
仓库健康度活跃按仓库活跃度与最近更新时间给出
可信度金综合仓库活跃度与验证结果

上面的结论来自上游最近一次自动化验证(2026-10-08): 同一套检查会在插件发新版后重跑,页面显示的是最新一次的逐项结果。

逐项检查结果

L1 · 已找到 ✓ 通过
  • L1.0_DEFAULTED_FROM_L3 由 L3 推定 默认通过——L3 安装规范已通过(全库 L3 扫描策略)
L2 · 结构化 ✓ 通过
  • L2.0_DEFAULTED_FROM_L3 由 L3 推定 默认通过——L3 安装规范已通过(全库 L3 扫描策略)
L3 · 安装规范 ✓ 通过
  • L3.1_INSTALL_COMMAND_PARSED 安装命令已解析 方式:安装规范解析
  • L3.2_DSH_VERSION_DECLARED DSH 版本已声明 方式:DSH 版本声明
L4 · 安装已测 ✓ 通过
  • L4.1_INSTALL_EXECUTED_CONFINED 受限沙盒内执行安装 方式:沙盒安装执行
  • L4.2_INSTALL_SUCCESS 沙盒安装成功 方式:沙盒安装执行
  • L4.3_ARTIFACT_CONFIRMED 安装产物已确认 方式:沙盒安装执行
L5 · 运行已测 ✓ 通过
  • L5.1_INSTALL_PASSED_SANDBOXED 沙盒安装通过 方式:沙盒安装执行
  • L5.2_WEB_BOOT_READY Web 启动就绪 方式:Web 启动
  • L5.3_HTTP_SERVED HTTP 服务响应 方式:HTTP 请求
  • L5.4_PLUGIN_INVENTORY_ACTIVE 插件清单中已激活 方式:插件清单查询

风险详情

  • 审查结论 通过
  • 结论说明 vet 静态分析未发现可疑行为,判定为干净(clean)。
  • 风险计数 严重 0 / 高 0 / 中 0
  • 风险详情 未发现严重或警告级问题。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 验证等级 L5:安装和运行都在沙盒里跑通过,装完能直接用的概率高。
  • 静态安全审查为低风险,没有发现明显可疑行为。
  • 有可直接复制的安装命令,不用自己翻文档找入口。
  • 标注了兼容的 DSH 版本(0.2.0-rc.2 等 3 个),按版本装不容易报错。
  • 列出了 5 项功能,能直接看出它解决什么问题。

先想清楚的地方

  • 需要同时装好同级依赖,漏装会启动失败。
  • 验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么。

更适合

  • 需要在浏览器与联网场景里给 DSH 补能力的人。
  • 想装完就能用、不想自己排依赖的人。
  • 能接受在本地装依赖、愿意自己确认权限的人。

不太适合

  • 只使用 DSH 官方内置能力、不接受第三方插件的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
插件验证等级安全审查星标兼容版本安装命令
dsh-browser-playwright-codex当前 L5 · 运行验证通过 低风险 1 0.2.0-rc.2 等 3 个 有
dsh-our-free-model L3 · 安装规范通过 低风险 8,796 未标注 有
dsh-web L3 · 安装规范通过 低风险 8,549 未标注 无
BrowserSkill L4 · 沙盒安装通过 低风险 8,456 未标注 有
dsh-pocket L5 · 运行验证通过 低风险 1,656 0.2.0-rc.2 等 12 个 有
Browser4 L4 · 沙盒安装通过 中风险 1,152 未标注 有

仓库档案

浏览器与联网
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方miqian-nomad仓库 dsh-browser-playwright-codex · 默认分支 main
分类浏览器与联网search
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言TypeScript仓库主语言
许可证MIT商用或二次分发前请确认条款原文
星标 / 复刻 / issue1 / 0 / 2收录时的数值,非实时
创建 / 更新2026-09-26 · 2026-10-06最后推送 2026-10-11
本站收录2026-09-27首次进入本站目录的时间

README 全文

30.0 KB
作者原文,中文版优先;只做安全转义,不改内容

dsh-browser-playwright-codex

>

一句话:让 AI 用你已经登录的账号在真实网页上干活 —— 填表、抓取列表、多标签查后台;浏览器窗口就在你桌面上、你随时看得见;遇到登录、验证码、原生弹框,它会停下来等你,绝不替你点「确定」。

In one line: the agent drives a visible, profile-backed browser window with the logins you
already have — filling in forms, scraping lists and working across tabs in real pages — through
accessibility snapshots with stable element refs, and it stops for logins, captchas and native dialogs
instead of guessing. No CSS-selector guessing, no full-DOM dumps.

# from npm
dsh plugin --profile  add dsh-browser-playwright-codex

# or straight from the repository
dsh plugin --profile  add github:miqian-nomad/dsh-browser-playwright-codex

为什么值得装 / What makes it different

  • 登录一次,一直用 — a profile-backed window plus an exported session state, so a closed window or
    a restarted harness comes back logged in.
  • 全程看得见,也不抢你的焦点 — a real window you can watch, minimise or take over; the provider
    keeps working while it is minimised (FOCUS-STEALING.md).
  • 遇事停下来叫人 — alert / confirm / prompt are parked and reported, answered only by an
    explicit browser_dialog call; a login, 2FA or captcha is handed back to you
    (DIALOG-POLICY.md).
  • ref 失效会明说 — per-document nonce refs; a stale ref fails fast with an explanation instead of
    silently clicking a different element.
  • 强力工具默认关闭 — browser_evaluate / browser_cdp are not registered at all unless your
    deployment opts in; this package ships both off.

安全一览 / Security at a glance — dsh.so's scanner flags this repository's one Critical finding, and that finding is the
implementation of browser_evaluate (its dynamic evaluation), which this package ships switched off.
SECURITY.md maps every finding to the gate that contains it, and explains what the plugin
can and cannot do with your logins (URL policy, CDP allow-list, dialog policy, no telemetry, and it never
types passwords or 2FA codes). Counts move as the scanner and the code change — their own report is the
live number.

Install

From npm (published since v0.5.1 — npmjs.com/package/dsh-browser-playwright-codex):

dsh plugin --profile  add dsh-browser-playwright-codex

Or straight from the repository / a checkout:

dsh plugin --profile  add github:miqian-nomad/dsh-browser-playwright-codex

# local development: clone, then link the checkout
dsh plugin --profile  add link:

Compatibility. Built and tested against DSH 0.2.0-rc.1 (@deepseek-ai/* peer ranges are deliberately
* so a newer harness still installs). After a harness upgrade, npm run doctor re-checks that every named
export this plugin imports still exists — that is the fast way to tell "the harness moved" from "the plugin broke".

lib/ ships in the repository (and there is deliberately no prepare hook), so a fresh clone loads
without a build step — npm run build is only needed after editing src/.

The bundle mounts three rows: the ctx.browser seam (service), the Playwright provider (playwright), and the model-facing tool family (tool).

Browser binary

The provider probes chromium → chrome → msedge → edge channels automatically; any installed Chromium-family browser works with zero download. To use Playwright-managed Chromium instead:

npx playwright-core install chromium
# Restricted networks (e.g. mainland China):
PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright npx playwright-core install chromium

Or pin a binary: launch.executablePath / launch.channel in the plugin config.

Tools

The default toolPrefix is browser_. Every action returns a fresh snapshot, so refs always come from the latest result. The registered set is capability-gated: browser_evaluate, browser_cdp and browser_extract appear only when their capability is switched on (their schemas are resident in the system prompt on every turn, so a tool that could only answer "disabled" would be pure prompt cost). Count the live surface with npm run cost — the shipped cordis.patch.yml keeps both power gates off (since 0.4.7), so a profile mounting this bundle sees 20 tools; 21 or 22 once your deployment opts into evaluate / cdp, 23 once extract is configured. How to opt in: SECURITY.md §1.

Tool Purpose
browser_navigate Open a URL (http/https only) and return the snapshot
browser_snapshot Snapshot the current page: URL, title, visible elements with ref= ids
browser_click Click the element with a ref — or a visible label the snapshot gave no ref, e.g. { text: "搜索设置" } — from the latest snapshot; a dialog raised by a click stays pending — answer it with browser_dialog
browser_hover Rest the pointer on a ref — or on a visible label the snapshot gave no ref, e.g. { text: "设置" } — so hover-revealed content appears (submenus, tooltips, previews, player controls); the returned snapshot names the target and notes whether the actionable ref count grew
browser_fill Replace an input's value; selects match by option label
browser_press Press a key (Enter, Tab, Escape, ArrowDown, …) on an element
browser_scroll Scroll the page or bring a ref into view
browser_back / browser_forward History navigation
browser_wait Wait a bounded duration for lazy content
browser_tabs / browser_open_tab / browser_switch_tab / browser_close_tab Tab management; browser_tabs marks the [active] tab the other tools act on
browser_screenshot PNG capture stored as a durable image attachment the model can view
browser_extract Structured extraction: natural-language instruction → one parsed JSON value
browser_evaluate Run one JavaScript expression in the page (disabled by default)
browser_dialog Answer the native dialog blocking the page: { accept: true } confirms, false cancels; errors with NO_DIALOG when nothing is pending
browser_click_at Precise native click: ref mode (geometric centre, Codex-style) or raw x/y mode; reports the actual landing element
browser_cdp Send one raw CDP command (DOM inspection / Input simulation allow-list only; disabled by default)
browser_close Close the session's browser window; the profile keeps login state, so the next call reopens signed in
browser_console_messages Read the page console messages captured for the current page (levels, text, source)
browser_network_requests Read the network requests captured for the current page (method, URL, status, resource type)

> 使用铁律: 状态检查 / 无效不盲试 / 页面内容不可信 / 登录红线 / 风控分类等 Codex 文档纪律,
> 见 codex-rules.md(A 层已内嵌进各工具 description; B 层供粘贴进 DSH profile / 系统提示)。

Snapshot example

URL: https://example.com/
Title: Example Domain
Refs: 12

- navigation "Main"
- link "Home" [ref=e1] -> /
- button "Go" [ref=e2]
- heading "Welcome" [level=1]
- textbox "Search" [ref=e3]

The model then calls browser_click with ref: e2. Invisible content is excluded, node and text caps bound the token cost, and truncation is flagged in the result.

An actionable element with no text of its own is named from its descendants — 搜索设置 renders as link "搜索设置" [ref=e7], and as `link "图标链接" [ref=e8]` — so a visible label and the ref that carries it always appear on the same line. A non-actionable child that merely repeats an ancestor name is folded away, so each label appears once, on the line that carries the ref; container roles are never named from their content (a shows its chosen option, the way a text input shows its value).

Configuration

All tunables are patchable through the profile's cordis.patch.yml (later layers win per row).

- id: browser
config:
provider: playwright                # explicit provider selection

- id: browser-playwright
config:
launch:
channel: chrome                   # or chromium / msedge / edge
headless: false                   # visible window you can watch and rescue
persistent: true                  # profile-backed window, login survives close
# profileDir: ~/.dsh/browser-profiles/playwright by default
viewport: { width: 1280, height: 800 }
navigationTimeoutMs: 30000
ignoreHTTPSErrors: false
allowedDomains: []                  # e.g. ['github.com'] restricts navigation
idleTimeoutMs: 600000               # close idle windows after 10 min; 0 = never
maxSessions: 8                      # LRU eviction (persistent mode: one window)
snapshot:
maxNodes: 500                     # token budget per snapshot tree
maxNameLength: 120
maxTextLength: 300

- id: browser-tool
config:
toolPrefix: browser_                # model-facing tool name prefix
allowEvaluate: false                # browser_evaluate gate
allowCdp: false                     # browser_cdp gate (DOM inspection / Input simulation allow-list)
registerDisabledTools: false        # register evaluate/cdp/extract even while off (discoverability vs resident prompt cost)
maxWaitMs: 60000                    # browser_wait bound
extract:
provider: deepseek-official       # optional: enables browser_extract
model: deepseek-v4-flash
maxInputChars: 20000             # caps the page text handed to that model
maxOutputTokens: 2000

browser_extract needs an auxiliary LLM route (extract.provider + extract.model); without one it fails with an actionable error. With a route configured, extract.maxInputChars bounds the page text in that prompt, and the prompt names the cap when it truncates. A gated tool is not registered at all while its capability is off, so its schema never reaches the system prompt; set registerDisabledTools: true to keep the whole surface discoverable (the tool then answers with the error naming the switch). The shipped layer in cordis.patch.yml keeps allowEvaluate and allowCdp off, matching the schema defaults and this sample: that file travels inside the package, so anything it enabled would be enabled for everyone who installs it. Opt in per deployment, in that deployment's own patch layer. browser_evaluate executes arbitrary page JavaScript; browser_cdp stays off until allowCdp: true, and even then only the allow-list in lib/cdp-policy.js passes — network, storage, cookie, security and arbitrary-JS (Runtime.evaluate) commands are rejected with CDP_DENIED.

Prefer a switch to editing config?

The companion package dsh-browser-toggle puts
this on a Settings card: enable/disable the browser, pick the page-reading mode, and turn the two
power tools on or off — no restart, no YAML. It is a separate package because
dsh-client-modules rejects a package mounted from multiple loader entries, and this plugin is
mounted as three (service, playwright, tool), while a Settings card needs a client module. The
card writes the gates into a managed block in the deployment's home-level cordis.patch.yml; the
package here stays untouched, so what you download is never the thing that decided to enable them.

Architecture

A swappable capability seam, one package:

  • service — ctx.browser: the provider registry with configured-or-auto selection semantics (a configured id must exist; one usable provider auto-selects; several require an explicit choice).
  • playwright — the provider. Persistent mode (default): one shared launchPersistentContext window on an independent profile directory (~/.dsh/browser-profiles/playwright), reused by every calling session — Codex-style personal browser. Login lives in the profile (durable cookies, localStorage) plus an exported state file (dsh-storage-state.json) that re-injects session cookies on relaunch (the browser drops those on close). The window auto-relaunches after an external close or crash, login intact. Set launch.persistent: false for the legacy shared-browser/per-owner-context mode — that mode writes no state file at all (the export is skipped rather than pointed at an empty path, which would have dropped cookie JSON into the process working directory). URL policy, idle disposal, and the injected snapshot engine apply to both.
  • tool — the consumer: defineTool-built tools whose canonical values are structured JSON and whose rendered text is the snapshot tree. Gated tools register only when their capability is on.
  • contract — the wire contract in one place: tool suffixes (and which are gated) plus every failure code. Registration, the load-time guard, the tests and the verify script all read it, so a renamed tool or changed code cannot drift apart silently.
  • compat — the boundary adapter for the harness packages: borrowed names (ToolCallId/CallId and friends, once per harness release) live here so a rename lands in one file instead of failing an import.

Other providers (remote browsers, Browserbase, Steel, …) can register into ctx.browser; the tool schemas stay unchanged. Browser sessions survive across tool calls; login state survives window close and harness restarts in persistent mode.

Development

npm install
npm test           # full suite: engine/action integration on real Chrome, policy, rendering,
# schema assembly, plus the realistic scenario suites below
npm run verify     # naming/folding + click/hover/dialog acceptance; self-contained, prints its own count
npm run verify:live  # same, plus a live sample of a real page (needs network)
npm run doctor     # does the installed harness still export everything this plugin imports?
npm run cost       # resident prompt cost of the tool schemas, per surface
npm run build      # tsc → lib/

scripts/ is self-contained: dsh-browser-verify.mjs, doctor.mjs and measure-prompt-cost.mjs live inside the package and resolve their imports relatively, so copying this directory elsewhere keeps every check runnable. A thin forwarder at D:\dsh-plugins\_deps\scripts\dsh-browser-verify.mjs keeps the old command (and the toolbox panel entry) working.

Test suites

Suite Command What it covers
Unit + engine integration npm test (included) Snapshot rendering, schema assembly, URL policy, provider actions on real Chrome
Realistic scenarios npm run test:scenarios Scripted-agent journeys over a realistic local store fixture: guest checkout with coupon and validation, login/session persistence, multi-tab research, lazy content, infinite scroll, modal dialogs, popups, screenshots, policy, owner isolation, idle disposal, snapshot budgets — at both the BrowserSession level and the model-facing ctx.tools.execute level (with fake attachments/LLM services)
Regression verify npm run verify The executable spec of snapshot naming/folding plus ref/text click-hover, the pending-dialog protocol and the tool surface (expected names derived from contract.ts)
Live smoke npm test:live Opt-in checks against the real internet (example.com, Wikipedia REST). Skipped unless DSH_BROWSER_LIVE=1; not part of CI

The scenario suites are the plugin's most realistic tests: they drive the browser the way an agent does — snapshot, find a ref, act, re-snapshot — and therefore double as executable documentation of the model experience.

From a DeepSeek Harness source checkout, load this plugin from TypeScript:

pnpm dsh web --patch ./browser-plugin/dev.cordis.yml

Model Experience

Tool schemas

The tool schemas join the system-prompt assembly through ctx.tools.register(); each carries a one-line task-oriented description. The registered set is derived from src/contract.ts and checked against it at plugin load, so a renamed or forgotten tool fails loudly instead of silently vanishing from the model's view. Snapshot results are bounded: at most maxNodes nodes, names capped at maxNameLength, and the truncation flag is explicit.

Token effect

One tool schema block per tool (small, fixed), plus per-call result text proportional to the visible page, capped by snapshot.maxNodes and name/text limits. Actions return a fresh snapshot, so interactive flows cost roughly one snapshot per step.

Measured with npm run cost (per-turn, resident in the system prompt):

Surface Tools Schema characters ≈ tokens/turn
Schema defaults (Config({}), no patch layer) 20 15,033 ≈ 4,176
Shipped bundle layer (this package's cordis.patch.yml: both power gates off) 20 15,033 ≈ 4,176
Everything registered (registerDisabledTools: true, plus extract) 23 17,886 ≈ 4,968

Three things changed here, and only one of them was about size. (1) The click family was rewritten so each rule is stated once instead of three times: -390 characters, with every rule, example and rationale pinned by tests/tool-descriptions.test.ts, so a trim that eats one fails the build. (2) A gated tool is registered only while its capability is live — browser_extract on this deployment: -456 characters ≈ 127 tokens/turn. (3) Four descriptions were corrected to match the code they describe (dialog blocking, the gated diagnostics browser_fill points at, persistent-mode browser_close, and browser_click_at's landing note), which added 211 characters back because the old wording promised behaviour the implementation did not have. Net: 18,065 → 17,886 characters with everything registered; the shipped layer's total is identical to the schema-defaults row above, because it keeps both power gates off — those schemas are not registered at all and cost nothing. What is left is per-tool prose rather than repetition, so a further cut trades away real guidance.

KV Cache effect

Tool schemas are static per registration and keep the prompt prefix stable. Result content varies with the page, invalidating reuse after each browser tool call, as with any tool result.

Browser state

The page state itself (DOM, cookies, storage) lives in the browser context and never enters the prompt except through snapshot or page-data results.

Further reading

Written for people deciding whether to hand an agent their browser:

  • 让 AI 用你已经登录的账号干活 — why session cookies are the hard part, and
    what the export does to a minimised window.
  • AI 开着浏览器抢你的焦点:三个根因 — all three traced into source, with a
    60-line reproduction script that needs no part of this plugin.
  • 遇到验证码和弹窗,为什么它不该替你点「确定」 — mechanism-level
    dialog parking, and the same philosophy behind stale refs failing loudly.
  • 官方 Discussions 发帖草稿 — a compatibility report in the format the
    community asks for, ready to paste.

Known Limitations and Deferred Work

  • Persistent mode is one shared window — all calling sessions drive the same profile-backed window and share its login state and tabs. Ideal for a personal assistant; if you need hard per-session isolation (separate logins per conversation), set launch.persistent: false and manage per-owner contexts, or run separate DSH profiles.
  • Headless servers must opt in — the bundle defaults to headless: false; on a headless/remote host set launch.headless: true.
  • Selector-free, not vision-free — interaction is a11y-tree based; purely visual widgets (canvas, WebGL, custom-drawn controls) may expose no refs. browser_screenshot + an image-capable model is the fallback.
  • Cross-origin iframes appear as leaf (frame) nodes without refs; same-origin frames are walked up to two levels deep.
  • Evaluate gate is config, not approval — enabling allowEvaluate trusts the model with arbitrary page JavaScript; compose it with the harness approval/permission policy for stricter control.
  • The package ships both power gates OFF, and that is deliberate — cordis.patch.yml is part of the package, so anything it enables is enabled for everyone who installs this. It therefore sets allowEvaluate: false and allowCdp: false (the code defaults), and each deployment opts in through its own profile patch (~/.dsh/profiles//cordis.patch.yml). A package that shipped them on would be handing every installer a backdoor they never asked for. Snippet:
# dsh replaces an entry's config object wholesale — list every key you rely on.
- id: browser-tool
config:
toolPrefix: 'browser_'
allowEvaluate: true    # registers browser_evaluate
allowCdp: true         # registers browser_cdp (needs a full DSH restart)
registerDisabledTools: false
maxWaitMs: 60000
  • Chromium family only — Firefox/WebKit channels are not probed; providers are swappable if another engine is needed.
  • Extract needs a dedicated model route — it does not reuse the main request's route; misconfiguration fails loudly at call time.
  • JS-driven navigations are not statically checkable — allowedDomains covers browser_navigate, browser_open_tab, every click path (browser_click, browser_click_at in both ref and raw-coordinate mode) and browser_switch_tab, but a button whose handler runs location.href = … can still leave the allowed hosts, and a tab that is already sitting on a disallowed host stays open (the agent simply refuses to drive it); deploy an external network guard for hard isolation.
  • Stability waits are bounded by design — a perpetually animating element falls back to a forced click on its current rect rather than stalling; a page that never settles is snapshotted after the cap. This is intentional: the agent must never hang.

Ref and lifecycle safety (fixed)

The scenario suites originally surfaced four hazards, now fixed and regression-tested:

  • Stale refs fail fast — refs carry a per-snapshot nonce, so after a client-side re-render a stale ref matches nothing and browser_click fails with REF_NOT_FOUND instead of silently acting on a different element.
  • Link clicks respect allowedDomains — every click path is checked before any input is delivered: browser_click, and browser_click_at in ref mode (the element's href) and raw-coordinate mode (the enclosing link found at the point). A disallowed host is rejected with URL_NOT_ALLOWED. javascript: links are exempt because they run in-page and navigate nowhere; other non-http(s) schemes stay refused.
  • A page-opened tab outside allowedDomains cannot be driven — a page can open a tab itself (target="_blank", window.open) and the plugin never sees that navigation, so the policy is applied where it can be: browser_switch_tab refuses to enter such a tab (the current tab is kept, the tab itself stays open for the user).
  • Idle disposal defers during operations — a navigation slower than idleTimeoutMs completes normally; disposal only fires when the session is truly idle.
  • Mid-navigation snapshots settle — a browser_snapshot racing a JS navigation waits for the new document and retries instead of surfacing a raw "Execution context was destroyed" error.

License

MIT

<!-- changelog:today -->

更新记录

(此列表只记 minor 里程碑;每个补丁版本见 CHANGELOG.md。)

0.5.0(2026-10-03)

  • CDP 白名单改为精确逐条列举(破坏性):DOM.get / DOM.query 这两个家族前缀不再放行任何东西 —— 它们此前多授权了 9 个 DOM 调用(getAnchorElement、getDetachedDomNodes、getSearchResults 等),而且会放行这两个家族将来新增的每一个方法。现在这份名单是 19 条完整方法名 + 等号匹配:名单没听过的名字一律拒绝,不需要有人注意到它出现了。同时经复核收回 9 条更早手工列上的调试器内部特性(performSearch、requestNode、getRelayoutBoundary 等)—— 那是有意选择,所以收它们是政策决定,不是修前缀溢出。允许面只收不放;插件自己的后台建页与窗口探测走内部会话,不受影响。
  • 测试从"钉例子"改成"钉性质":测试里写一份独立的同一份名单,与源码表双向相等(加一条/删一条都必须同时改两处,任何放宽都会出现在 diff 里);再加 9 类探针(大写/小写/数字/点号后缀、大小写互换、截断、尾空格、整域前缀)过真函数,断言"被接受的集合恰好等于复审名单"。测试先行:旧实现下这 3 条会红(DOM.getDocumentZzz 骑进白名单、DOM.getAnchorElement 被放行、两份名单不一致)。
  • 升级提示:如果你的脚本用 browser_cdp 调过被收回的那 18 个方法,会开始收到 CDP_DENIED;要加回来是"改代码 + 改测试"两处,不是改配置。

0.4.0(2026-09-30)

  • 设置页多了一组选择:在「允许 AI 操作网页」开关下面,多了「页面识别方式」——兼容模式(插件自己找按钮输入框,用得最久)与智能模式(用浏览器官方的"页面说明书",复杂页面通常更准;读不出来会自动退回兼容模式)。选完下一步操作就生效,不用重启、不用改配置文件;卡片底部写着"当前:X(你选的 / 默认)"。多选一用的是和"搜索提供方"卡片一样的单选行,不是开关,一眼看去是同一套。
  • 改名为 dsh-browser-playwright-codex:改名是跨文件操作 —— 本包 cordis.patch.yml 的三个 name:、dsh-browser-toggle 的 import &#x27;…/runtime-state&#x27; 与它的 node_modules 链接、以及 profile 链接,全都必须一起走。少改一处,插件加载就 MODULE_NOT_FOUND(已实测:旧名在两个 profile 均已解析失败,新名可解析)。
  • 持久化开关文件名故意保持旧拼写(~/.dsh/dsh-browser-playwright.state.json):那是用户状态,改名会让设置页的开关被静默重置。
  • 中文插件元数据:新增 locale/en.json / locale/zh.json,并在 exports 加 &quot;./locale/*.json&quot;、在 files 加 locale —— 少了 exports 这一行,harness 的 require.resolve 会失败并静默回退英文。
  • 新增可选 aria 快照引擎(snapshot.engine: &#x27;aria&#x27;,默认仍是 &#x27;legacy&#x27;):用 Playwright 官方 locator.ariaSnapshot({ mode: &#x27;ai&#x27; }) 取语义树,再对齐回本项目稳定的 data-dsh-ref,所以 ref、REF_PATTERN、refLocator 全都不变。
  • 新增增量快照 diff(snapshot.diff,默认关):按稳定 ref 输出 + / - / ~ 增量;ref nonce 变化即标注"导航重置",树被截断时退回整棵树。
  • 修掉第一版 aria 引擎的真实缺陷:解析器按自造方言写(- role &quot;name&quot; -&gt; href、行尾无其他内容),而真实输出每个容器行都以 : 结尾、href 走更深的 - /url: 子行、文本是 - text: …。16 个节点的页面只解析出 5 个 —— 层级与链接全丢,却仍报成功(所以不会回退)。已用真实页面实测前后对比。
  • 格式漂移现在会大声失败:读不懂的行会被收集(parseAriaSnapshotWithStats)并让本次捕获返回 missing: true,captureAria 随即回退 legacy DOM 引擎,绝不把空树交给模型。
  • aria 测试改用真实抓取的 YAML(2026-09-30 从 playwright-core 1.62 实抓),不再用解析器自己方言手写的 fixture。
  • CDP 白名单收紧为逐方法列举:去掉 Input. 族前缀,只留 Input.dispatchMouseEvent / dispatchKeyEvent / dispatchTouchEvent / insertText;Input.setIgnoreInputEvents、synthesizeScrollGesture、dispatchDragEvent 及未来的 Input.* 默认拒绝,并新增守卫测试断言任何条目都不得以 . 结尾(旧的守卫恰好允许了一条)。

0.3.0(2026-09-26)

  • 源码化:插件重新变成有源码的工程 —— src/ 10 个 TypeScript 模块是唯一真源,lib/ 由 npm run build 生成(10 个 .js + 10 个 .d.ts),不再手改产物。
  • 代码规范:引入 Prettier 配置(.prettierrc.json),npm run format / npm run format:check 统一格式;严格类型检查 0 错误。
  • 新增两只诊断工具:browser_console_messages(控制台报错)与 browser_network_requests(网络请求),用于"点了没反应"时快速定位原因。
  • 接口与实现同步:BrowserSession 补齐 9 个实现里已有的方法;errors.ts 补齐 12 个实际在用的错误码;BrowserSnapshot 补 dialogNote / landingNote;TabInfo 补 active;runtime-state / cdp-policy 新增类型声明。
  • 依赖范围修正:devDependencies 与 peerDependencies 对齐,可在当前 DSH 版本下安装。

常见问题

9 问
答案由本站依据条目字段整理,不引用上游原文
dsh-browser-playwright-codex 怎么安装?

在 DSH 里执行 `dsh plugin --profile web add dsh-browser-playwright-codex@0.5.3` 即可。对应的 npm 包名是 `dsh-browser-playwright-codex`。

dsh-browser-playwright-codex 的验证等级是什么意思?

L5 · 运行验证通过。在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来

dsh-browser-playwright-codex 安全吗?

低风险。vet 静态分析未发现可疑行为,判定为干净(clean)。

dsh-browser-playwright-codex 装之前要先确认什么?

先看它会读写哪些文件、执行哪些命令、连接哪些网络地址;验证等级只说明装得上、跑得起来,不等于安全。涉及密钥或系统权限的,建议先在隔离环境试装。

dsh-browser-playwright-codex 支持哪些 DSH 版本?

上游记录的兼容版本包括 0.2.0-rc.2、0.2.0-rc.1、0.1.7-rc.2。

dsh-browser-playwright-codex 需要什么运行环境?

Node.js ^22.19.0 || >=24.0.0;需要同时安装 @deepseek-ai/cordis@*、@deepseek-ai/dsh-llm@*、@deepseek-ai/dsh-tools@*。环境不满足时安装会失败,建议先确认本机版本。

dsh-browser-playwright-codex 用的是什么许可证?

上游标注为 MIT。商用或二次分发前请到仓库确认许可证原文。

dsh-browser-playwright-codex 有哪些功能?

Playwright 有头浏览器自动化、无障碍快照与元素交互、几何点击与 CDP 策略层、持久化 profile 与登录态导出、修复最小化窗口被拽回。

这条记录的数据可靠吗?

本站按仓库名去重后合并整理,字段以作者仓库与 npm 元数据为准;安装命令、仓库地址与 README 保持原文,带 L4 / L5 标记的安装命令已在隔离沙盒里真实跑通。

浏览器与联网
按星标排序,可作替代方案

dsh-our-free-model

dsh-our-free-model

在 DeepSeek Harness 中装上这个 DSH plugin,无需登录、注册或填 API Key,即可直接调用 DeepSeek

L3 · 安装规范通过 8,796 星

dsh-web

dsh-web

侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。

L3 · 安装规范通过 8,549 星

BrowserSkill

BrowserSkill

BrowserSkill 的 DeepSeek Harness 浏览器自动化桥接插件,通过原生浏览器工具控制可见的 Chrome 和 Edg

L4 · 沙盒安装通过 8,456 星

dsh-pocket

dsh-pocket

DSH Pocket 让 DeepSeek Harness 装进口袋:电脑跑 dsh web,手机扫码即实时同步访问(局域网+公网),人在外

L5 · 运行验证通过 1,656 星

Browser4

Browser4

L4 · 沙盒安装通过 1,152 星

agentrq

agentrq

L4 · 沙盒安装通过 1,140 星

miqian-nomad 的其它插件

1 个

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 2026-10-08。