DeepSeek Harness Plugin Hub

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

探索

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

社区

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

相关链接

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

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

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

dsh-browser-vision

Browser Vision

适用于 DeepSeek Harness 的可查看页面的浏览器工具:通过 CDP 使用 browser-use 驱动真实 Chrome,并使用 deepseek-v4-flash-vision-exp 读取页面,因此可以读取画布文本、图像中的文本和渲染的图表。支持基于 Schema 的 JSON 提取、Markdown 输出,以及按运行统计令牌和成本

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

npx -y @deepseek-ai/dsh plugin --profile web add github:tristan-mcinnis/dsh-browser-vision#f1ba8f840c5e906843f719a7b7cd68a1ee074461
README兼容性版本

说明

适用于 DeepSeek Harness 的可查看页面的浏览器工具:通过 CDP 使用 browser-use 驱动真实 Chrome,并使用 deepseek-v4-flash-vision-exp 读取页面,因此可以读取画布文本、图像中的文本和渲染的图表。支持基于 Schema 的 JSON 提取、Markdown 输出,以及按运行统计令牌和成本。

兼容性与来源证明

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

DSH 兼容范围
*
运行环境
any
发布来源
github
Registry 更新时间
2026/8/22

版本

0.2.0stable
2026/8/22

相关插件

正在加载相关插件…

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

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

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

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

认领这个 Plugin →
报告问题

相关插件

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

Browser Skill Dsh Plugin@wxg-prc-cpg/browser-skill-dsh-plugin向模型提供 BrowserSkill 浏览器自动化(browser_* 工具)的 DeepSeek Harness 工具插件Weknora@wxg-prc-cpg/dsh-weknora适用于 DeepSeek Harness (dsh) 的 WeKnora 知识检索工具:通过自有知识库进行语义搜索、文档阅读以及 RAG/代理回答。Free Searchdsh-free-searchDeepSeek Harness 的免费网页搜索:13 个引擎(Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable/Firecrawl 无需密钥;Parallel/Perplexity/SerpBase/DeepSeek 需要密钥),支持时间筛选、平台搜索和 web_fetch,并提供网页设置界面。Find Plugindsh-find-plugin在代理中查找 DeepSeek Harness 插件——实时搜索 GitHub 上的 dsh-plugin 主题,并按星标数排序。

README

dsh-browser-vision — a browser tool for DeepSeek that can see the page

A fully contained browser-use tool driven by DeepSeek through DeepSeek's OpenAI-compatible API. It is designed as a cheap and fast alternative to running browser-use with a general-purpose model, and to be callable from any agent or harness (Codex, Claude Code, OpenCode, custom evals, CI, ...) via a plain CLI with a machine-readable JSON mode.

Since DeepSeek shipped deepseek-v4-flash-vision-exp, the agent can look at the page, not just read its DOM. That model is priced identically to the text Flash model, and a screenshot costs at most 384 input tokens, so vision is no longer a premium feature to be switched off for cost. It is on by default, and the eval suite says that is also the cheapest setting.

What makes it cheap and fast (all overridable via env):

  • DeepSeek Flash (deepseek-v4-flash) / Flash Vision (deepseek-v4-flash-vision-exp) — far cheaper and faster than GPT-class models, and the same price as each other.
  • Vision by default (DSBROWSER_VISION_MODE=on) — a screenshot every step, because a blind agent burns whole step budgets on tasks it cannot see, and steps cost more than pictures.
  • Flash mode, no judge, no planning — fewer extra LLM calls per task.
  • One shared browser — a single Chrome instance is reused across all tasks in a process; the eval suite runs all cases in one browser instead of one Chrome per case.

Vision

DSBROWSER_VISION_MODE (or --vision) has three settings:

ModeModelBehaviourUse it when
on (default)deepseek-v4-flash-vision-expA screenshot rides along with every stepGeneral use, and everything visual
autodeepseek-v4-flash-vision-expDOM-driven; browser-use registers a screenshot tool the agent calls when it decides it needs oneLong text-heavy runs where most steps genuinely need no picture
offdeepseek-v4-flashDOM only, no screenshots everPure text and form work, or when no vision quota is available

Vision works the same headless and headed — screenshots come off the same CDP call either way. dsbrowser "task" --no-headless --vision on is a supported way to watch the agent look at a page, and the eval suite takes --no-headless for exactly that.

What vision unlocks, which the DOM cannot answer at all:

  • text drawn on a <canvas> (voucher codes, editors, map labels)
  • text baked into an image (scanned invoices, screenshots-in-pages, banners)
  • charts and any answer that lives in a shape rather than a string
  • "which of these is highlighted / greyed out / overlapping" layout questions

Measured

Six cases, three attempts each, per mode, on the offline fixture suite (dsbrowser-eval --vision all --repeat 3), off-peak pricing:

modepassedDOM casesvision casesmedian latencyscreenshotscost
off7/187/90/933.7s0$0.1021
auto14/185/99/98.3s10$0.0310
on18/189/99/96.6s111$0.0318

The surprise is the cost column. on sent 111 screenshots and still cost a third of what off cost sending none. A blind agent does not fail fast, it flails: it spends its whole 20-step budget re-reading a DOM that does not contain the answer, and twenty text steps cost far more than one 384-token picture. Vision is not a premium you pay for accuracy here — it is what makes the run short enough to be cheap.

auto is the weak middle. It solved every vision case, but it did worse on the plain DOM cases than either extreme, and it saves nothing over on.

One machine, one afternoon, n=3. Re-run it yourself before trusting it: dsbrowser-eval --vision all --repeat 5.

Cost of looking

DeepSeek resizes every image so its pixel count is roughly that of an 800×800 image, which caps an image at 384 input tokens. At the off-peak cache-miss rate of $0.22 / 1M input tokens, a screenshot costs about $0.00008. A whole 20-step run with a screenshot at every step adds under a cent.

Two consequences worth knowing:

  • Never use detail: low. It crops to 512×512 first, and on-page text stops being legible — measured on the fixture, the model invented a confirmation code rather than reading it. Every image this tool sends is pinned to detail: high.
  • Downscale the capture, not the detail. DSBROWSER_SCREENSHOT_SIZE=1024x768 shrinks the upload without changing what DeepSeek tokenizes.

Use it from DeepSeek Harness

This repo is also a DSH plugin. Install the plugin, then the engine:

dsh plugin --profile web add "github:tristan-mcinnis/dsh-browser-vision"
uv tool install "git+https://github.com/tristan-mcinnis/dsh-browser-vision"

Restart the profile afterwards (the web profile has HMR disabled). Put DEEPSEEK_API_KEY in the environment — the plugin never stores or forwards a key, it only inherits the environment the engine runs in.

Three tools are registered:

ToolWhat it does
browser_vision_taskRun a web task in plain language and get the answer. Navigates, clicks, types, fills forms, and reads what is only visible as pixels.
browser_vision_extractExtract fields from a page as JSON validated against a schema you pass in, so nothing has to be re-parsed downstream.
browser_vision_statusReport whether the engine is installed, so an install problem is distinguishable from a task failure.

Plugin options (in cordis.patch.yml, or Settings → Plugins):

OptionDefaultMeaning
commanddsbrowserPath to the engine executable
visiononDefault vision mode for tool calls
maxSteps20Default step cap
headlesstrueRun Chrome headless
timeoutMs300000Hard timeout for one task

Requirements

  • Python 3.11 or 3.12
  • A Chrome/Chromium binary on the system (browser-use ≥0.13 drives Chrome over CDP — Playwright is not used, so playwright install is neither needed nor available)

Install

With uv (recommended):

cd ~/Documents/code/deepseek-browser-use
uv venv --python 3.12 .venv
VIRTUAL_ENV=.venv uv pip install -e '.[dev]'
cp .env.example .env   # then add your DEEPSEEK_API_KEY

With pip:

python3.12 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'

This installs the dsbrowser package plus two console scripts: dsbrowser (alias deepseek-browser) and dsbrowser-eval.

Secrets: plain env or 1Password CLI

The DeepSeek key can come from the environment/.env (DEEPSEEK_API_KEY) or from 1Password through the op CLI. Point DEEPSEEK_API_KEY_OP at a secret reference and the tool resolves it with op read --no-newline:

# .env
DEEPSEEK_API_KEY_OP="op://Personal/DeepSeek/api key"

op:// references also work directly as DEEPSEEK_API_KEY. The op CLI must be installed and authenticated (op signin, or export OP_SERVICE_ACCOUNT_TOKEN for headless/CI use). No keychain involvement in the tool itself — and Chromium is explicitly steered away from the macOS keychain too (see below).

CLI

dsbrowser "Open example.com and return its page title"
dsbrowser "Read the voucher code drawn on the canvas at example.com/ticket" --vision on
dsbrowser "task" --vision off              # DOM only, cheapest floor
dsbrowser "task" --json                    # machine-readable output
dsbrowser "task" --max-steps 40            # override step cap
dsbrowser "task" --no-headless --vision on # watch it, and let it look
dsbrowser "task" --model deepseek-v4-pro
python -m dsbrowser "task"                 # module form

Structured output

Reading a scanned invoice with --schema, which is the whole tool in one call — see the page, extract the fields, return validated JSON:

{
  "invoiceNumber": "5512-B",
  "totalDue": "$128.40",
  "lineItems": [
    {"label": "Standing desk", "amount": "$96.00"},
    {"label": "Cable tray", "amount": "$18.40"},
    {"label": "Delivery", "amount": "$14.00"}
  ]
}

Nothing above is in the DOM: the invoice is a PNG. One LLM call, 10.9s, $0.0013.

Pass a JSON Schema and the answer comes back as a validated object instead of prose, so a calling agent does not need a second model call to parse it:

dsbrowser "Open https://example.com/pricing and list every plan" --json --schema '{
  "type": "object",
  "properties": {
    "plans": {"type": "array", "items": {
      "type": "object",
      "properties": {"name": {"type": "string"}, "price": {"type": "string"}},
      "required": ["name", "price"]
    }}
  },
  "required": ["plans"]
}'

--schema also takes a path to a .json file. Objects, arrays, primitives, enums, unions and local $refs are supported; the top level must be an object, so wrap a bare list in a property. Optional properties come back as null rather than forcing the agent to invent a value it could not find.

For prose rather than fields, --markdown asks for the page content as clean Markdown with the navigation, ads and cookie banners left out.

JSON contract (for agents and harnesses)

With --json, stdout carries exactly one JSON object and stderr stays clean:

{
  "tool": "dsbrowser",
  "version": "0.2.0",
  "success": true,
  "result": "PLUM-4482",
  "steps": 3,
  "duration_s": 14.2,
  "error": null,
  "model": "deepseek-v4-flash-vision-exp",
  "vision_mode": "auto",
  "usage": {
    "llm_calls": 4,
    "images_sent": 1,
    "prompt_tokens": 18422,
    "completion_tokens": 611,
    "cached_tokens": 12800,
    "cost_usd": 0.00119
  }
}

usage.images_sent is the number of screenshots the model actually looked at — in auto mode that is how you tell whether the agent needed to see the page. cost_usd uses DeepSeek's published rates and accounts for the peak/off-peak window and cache hits; it is an estimate, not a bill.

Exit codes: 0 task completed · 1 task failed (agent/network/model error, error is set) · 2 configuration error (e.g. missing DEEPSEEK_API_KEY, or vision on with a model that has no image input).

Calling it from other agents

Any harness that can run a shell command can use it:

result=$(dsbrowser "Summarize the pricing page at https://example.com/pricing" --json)
# then parse $result with jq: .result, .steps, .usage.cost_usd, .error
# Python harness
import json, subprocess
out = subprocess.run(["dsbrowser", task, "--json"], capture_output=True, text=True, check=False)
payload = json.loads(out.stdout)
print(payload["result"], payload["usage"]["cost_usd"])

Or use it as a library:

import asyncio
from dataclasses import replace
from dsbrowser import Config, DeepSeekBrowserAgent

async def main():
    config = replace(Config.from_env(), vision_mode="on", headless=False)
    async with DeepSeekBrowserAgent(config=config) as agent:
        outcome = await agent.run_task("Read the code on the canvas at example.com/ticket")
        print(outcome.result, outcome.images_sent, outcome.cost_usd)

asyncio.run(main())

Configuration

VariableDefaultMeaning
DEEPSEEK_API_KEY—required (or DEEPSEEK_API_KEY_OP)
DEEPSEEK_API_KEY_OP—1Password CLI secret reference (op://Vault/Item/field) resolved via op read
DEEPSEEK_BASE_URLhttps://api.deepseek.comOpenAI-compatible endpoint
DEEPSEEK_MODELdeepseek-v4-flashmodel used when vision is off
DEEPSEEK_VISION_MODELdeepseek-v4-flash-vision-expmodel used when vision is auto or on
DSBROWSER_VISION_MODEautooff · auto · on (legacy DSBROWSER_USE_VISION=true/false still parses)
DSBROWSER_SCREENSHOT_SIZE—WIDTHxHEIGHT to downscale screenshots before upload
HEADLESStrueheadless browser (vision works either way)
MAX_STEPS20max agent steps per task
DSBROWSER_CHROME_ARGS--password-store=basic,--use-mock-keychainextra Chrome flags; defaults keep Chromium off the macOS keychain
DSBROWSER_FLASH_MODEtruebrowser-use flash-mode prompt optimization
DSBROWSER_USE_THINKINGfalseagent step-by-step thinking (slower, sometimes better)
DSBROWSER_USE_JUDGEfalseextra judge pass to validate completion (slower, costs more)
DSBROWSER_ENABLE_PLANNINGfalseplanner sub-agent for long tasks (slower)
DSBROWSER_DISABLE_THINKING

Evaluation

The offline suite serves a local deterministic website. Three cases are answerable from the DOM; three are answerable only by looking, which is what makes the suite able to tell the vision modes apart — with --vision off those three are expected to fail.

CaseCapabilityNeeds visionSuccess signal
search_and_extracttype, click, extractnoexact name, price, and path
navigate_and_submit_formnavigate, fill, select, check, submitnodeterministic confirmation code
negative_searchhandle empty statenozero results reported
canvas_coderead text drawn on a <canvas>yesthe voucher code PLUM-4482
image_invoiceread text baked into an imageyesinvoice number and total
chart_readinginterpret a chart rendered as an imageyestallest month and its printed value
# Offline contract tests — no API key, no browser
pytest -q

# Live eval — uses DeepSeek tokens
dsbrowser-eval                      # current DSBROWSER_VISION_MODE
dsbrowser-eval --vision all         # sweep off/auto/on over identical tasks
dsbrowser-eval --vision-only        # just the three see-the-page cases
dsbrowser-eval --vision on --no-headless   # same suite, headed browser
dsbrowser-eval --repeat 5 --json    # five attempts per case
dsbrowser-eval --case canvas_code
python -m dsbrowser.evals

Each run writes raw outputs, errors, timings, per-case token usage and cost, and a per-mode summary to eval-results/run-<timestamp>.json. The summary line reports pass rate split into DOM cases and vision cases, median latency, screenshots sent, and total cost, so the modes can be compared on identical work. Run the suite at least five times before comparing configurations. The local fixture measures agent reliability without public-site drift — keep public-site tasks (like a Hacker News one) as separate realism tests, since network state and page changes make them unsuitable as a regression gate.

Notes

  • browser-use disables vision for DeepSeek and this tool undoes it. agent/service.py still contains if 'deepseek' in self.llm.model.lower(): use_vision = False, written before a DeepSeek vision model existed. DeepSeekBrowserAgent restores the setting on the constructed Agent; without that repair the agent silently never takes a screenshot, whatever you configure.
  • Images are legal in user messages only. DeepSeek answers 400 "Image in system message is unsupported" otherwise, and a single such message kills a whole run. Every request is sanitized before it goes out: images found in system or assistant messages are replaced with a text placeholder.
  • Vision needs the vision model. Sending an image to deepseek-v4-flash returns 400 "This model does not support image", so the configuration is rejected up front with exit code 2 rather than failing mid-run.
  • Structured output via response_format: json_object. DeepSeek's function-calling backend unwraps nested single-key objects, so browser-use's AgentOutput action union ({action_name: params}) came back as bare param dicts that failed pydantic validation. Routing the schema through JSON-object mode (with the schema embedded in the system prompt) makes DeepSeek return the exact expected shape — verified to keep working when the message also carries a screenshot.
  • Usage accounting is ours. Upstream ChatDeepSeek returns usage=None on every path, so this project's DeepSeekBrowserLLM reads DeepSeek's prompt_cache_hit_tokens / prompt_cache_miss_tokens itself and aggregates per run. That is what makes cost_usd and the eval's cost column possible.
  • Browser reuse with keep_alive=True. Agent.run() kills the browser session after every task unless the profile opts out; without this, a shared browser dies after the first task ("CDP client not initialized").
  • deepseek-v4-flash reasons by default, so DSBROWSER_DISABLE_THINKING=true sends thinking: {"type": "disabled"} on every request via an httpx event hook — measured at ~10x fewer tokens on a trivial call (98 → 10).
  • browser-use ≥0.13 no longer uses Playwright — it drives a system Chrome/Chromium over CDP. Make sure Chrome is installed.
  • Chromium is launched with --password-store=basic and --use-mock-keychain by default, so headless runs never read or prompt against the (often stale) macOS keychain. Override with if you need real password storage in the profile.
true
disable DeepSeek's native reasoning (thinking: disabled); ~10x fewer tokens and much lower latency
DSBROWSER_CHROME_ARGS