npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

visual-review

v1.0.1

Published

DSH plugin: renders images inline in DeepSeek Harness Web chat and gives text-only models vision — cloud multimodal API first, local Qwen3-VL fallback.

Readme

visual-review

License: MIT

DeepSeek Harness(DSH)Web 界面打造的双面插件:让聊天界面直接显示图片,并让模型解读图片

  • 图片显示:用户粘贴 / 上传的图片(PNG / JPEG / WebP / GIF)会直接渲染在对话气泡里。
  • 视觉解读visual_review 工具调用视觉多模态模型,返回图片的中文文字描述(文字、物体、人物、场景、图表等)。
  • 双引擎:云端优先(任意 OpenAI 兼容的多模态 chat/completions API,零本地依赖);未配置时自动回退本机 Qwen3-VL-8B(数据不出本机)。
  • 无需更换模型:插件在发送路径上把「图片块」转换成「带附件 ID 的文本注解」,任何本身看不到图片的文本模型都能配合工作。

目录

功能特性

| 能力 | 说明 | | --- | --- | | 聊天界面渲染图片 | 客户端插件注入 conversation.chat.node 渲染槽,把图片块渲染为 <img>(经 /vr-image 路由取字节) | | 模型“看见”图片 | /api/session.prompt 拦截 + agent/pre-step 兜底:图片块 → 注解文本,附带附件 ID,提示模型调用工具 | | 图片解读工具 | visual_review:传 attachment_id(会话图片)或 image_path(本地文件)即可分析 | | 云端引擎 | OpenAI 兼容 chat/completions,图片以 data: URL 内联发送,支持 content / reasoning_content 返回 | | 本机引擎 | 内置 JSON-lines worker,加载本地 Qwen3-VL-8B 推理,图片与结果均不出本机 | | 配置工具 | visual_review_config:查看 / 更新云端 url / api_key / model,一键切换引擎 |

架构与工作原理

┌──────────────────────────── DSH Web 前端 ────────────────────────────┐
│  聊天界面(React)                                                    │
│    └─ visual-review 客户端插件(lib/client.js)                        │
│         注入 conversation.chat.node 渲染槽                             │
│         └─ 图片块 → <img src="/vr-image/sha256:xxx">                  │
└───────────────┬─────────────────────────────────────────┬────────────┘
                │ ① /api/session.prompt(图片块→注解)      │ ② /vr-image 取图片字节
┌───────────────▼─────────────────────────────────────────▼────────────┐
│                        DSH Host(插件 Host 端 lib/index.js)          │
│  • /api/session.prompt 拦截路由:把 image 块存为附件,替换为注解文本    │
│  • agent/pre-step 兜底(幂等):模型侧消息里的 image 块 → 注解          │
│  • /vr-image 路由:仅回环地址可访问,从附件存储读取图片字节             │
│  • visual_review 工具:云端优先 → 本机回退                             │
│        ├─ 云端:node 内联脚本 → OpenAI 兼容 chat/completions           │
│        └─ 本机:spawn Python worker(server/visual_review_server.py)  │
└───────────────────────────────────────────────────────────────────────┘

三个关键机制:

  1. 发送拦截(图片 → 注解)。客户端发送 session.prompt 时,插件拦截请求,把内容中的 image 块交给附件服务保存,得到附件 ID(形如 sha256:xxx),再替换成一段文本注解:

    [用户上传了图片附件(image/png,640x360px)。你无法直接查看图片,
    请调用 visual_review 工具并传入 attachment_id="sha256:xxx" 获取图片的视觉解析。]

    agent/pre-step 钩子对模型侧消息做同样的转换,作为兜底且幂等。于是文本模型也能“看见”图片——它只需按注解调用工具。

  2. /vr-image 路由(字节 → 渲染)。客户端渲染槽把注解里的附件 ID 提取出来,渲染为 <img src="/vr-image/<id>">;Host 端从附件存储读回图片字节返回。该路由仅接受回环地址(127.0.0.1 / ::1)的请求。

  3. visual_review 工具(图片 → 描述)。模型拿到附件 ID 后调用工具:优先读取 $DSH_HOME/visual_review.config.json 走云端;未配置云端则启动/复用本机 Python worker,把图片以 base64 经 stdin 发送,worker 返回生成文本。

本机 worker 通信协议(JSON-lines,每行一个 JSON 对象):

请求  → {"id":1, "kind":"describe", "image_b64":"...", "prompt":"...", "max_new_tokens":256}
响应  → {"id":1, "ok":true, "text":"图片中有一只橘猫……"}
就绪  → {"event":"ready"}   (模型在后台线程加载,describe 请求会等待该事件)

目录结构

visual-review/
├── lib/
│   ├── index.js                  # Host 端插件:工具、路由、发送拦截、worker 管理
│   └── client.js                 # 客户端插件:聊天界面图片渲染
├── server/
│   └── visual_review_server.py   # 本机推理 worker(Qwen3-VL-8B,JSON-lines 协议)
├── config/
│   └── visual_review.config.example.json  # 云端配置模板(含 API Key 占位符)
├── install/
│   ├── install.sh                # 一键安装到 DSH profile
│   └── cordis.patch.yml.example  # 手动安装时追加到 cordis.patch.yml 的片段
├── examples/
│   └── test_image.png            # 测试图片
├── assets/
│   ├── qr-official-account.jpg   # 公众号二维码
│   └── qr-group.png              # 交流群二维码
├── cordis.patch.yml              # dsh.bundle 安装补丁层(`dsh plugin add` 用)
├── package.json                  # 插件清单(exports host/client 双入口 + dsh.bundle manifest)
├── README.md / README.en.md      # 中文 / English 文档
├── LICENSE                       # MIT
└── .gitignore

环境要求

  • DSH(DeepSeek Harness)Web profile(~/.dsh/profiles/web),Node.js ≥ 18(需要全局 fetch)。
  • 视觉引擎二选一
    • 云端模式(推荐,最简单):任意 OpenAI 兼容的多模态 chat/completions API(如 SiliconFlow、OpenAI、DeepSeek、本地 vLLM 等)。
    • 本机模式:Python 3.10+,torchtransformers(≥ 4.57,支持 Qwen3-VL)、Pillow,以及本地模型文件 Qwen3-VL-8B-Instruct(可换为任意兼容的 Qwen3-VL 权重)。

安装

方式 A / B 无需依赖外部发布渠道;插件已声明 dsh.bundle manifest(cordis.patch.yml),因此也支持官方 dsh plugin add 安装(方式 C,推荐,最简单)。

方式 C:官方 dsh plugin add(推荐)

npm 发布后:

dsh plugin --profile web add visual-review

npm 尚未发布或想装最新版时,可直接从 GitHub 安装:

dsh plugin --profile web add github:wang-bool/visual-review

安装后重启 dsh web 并刷新浏览器。

方式 A:一键脚本

git clone <本仓库> visual-review
cd visual-review
bash install/install.sh

脚本会把插件复制到 $DSH_HOME/profiles/web/node_modules/visual-review/,并在 cordis.patch.yml 中注册(幂等,重复执行安全)。可用 DSH_HOME / DSH_PROFILE 环境变量指定其它数据目录或 profile。

方式 B:手动安装

  1. 将插件包放入 profile 的 node_modules

    DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
    PROFILE_DIR="$DSH_HOME/profiles/web"
    mkdir -p "$PROFILE_DIR/node_modules/visual-review"
    cp -r package.json lib server "$PROFILE_DIR/node_modules/visual-review/"
  2. $PROFILE_DIR/cordis.patch.yml 末尾追加(参考 install/cordis.patch.yml.example):

    - insert:
        - id: visual-review
          name: 'visual-review'
  3. 重启 DSH web 服务并刷新浏览器。宿主日志出现以下输出即加载成功:

    visual_review: 全局插件已加载 (config=.../visual_review.config.json)
    visual_review: /vr-image 图片路由已注册
    visual_review: /api/session.prompt 拦截路由已注册

配置

云端引擎(推荐)

$DSH_HOME/visual_review.config.json(默认 ~/.dsh/visual_review.config.json)写入:

{
  "url": "https://api.siliconflow.cn/v1/chat/completions",
  "apiKey": "sk-xxxx",
  "model": "Qwen/Qwen3.5-35B-A3B"
}

也可以在会话中让模型调用 visual_review_config 工具填写 url / api_key / model(只传需要修改的字段;三项都留空表示清除云端配置、回退本机引擎)。

该文件包含明文 API Key,务必加入 .gitignore 并注意文件权限(本仓库的 .gitignore 已包含)。

本机引擎

未配置云端时自动回退。需要本地模型:

huggingface-cli download Qwen/Qwen3-VL-8B-Instruct

模型目录解析顺序:命令行参数 → 环境变量 VISUAL_REVIEW_MODEL_DIR → 默认 ~/.cache/huggingface/hub/models--Qwen--Qwen3-VL-8B-Instruct

环境变量

| 变量 | 默认值 | 说明 | | --- | --- | --- | | DSH_HOME | $HOME/.dsh | DSH 数据目录,visual_review.config.json 存放处 | | VISUAL_REVIEW_SERVER | 插件自带 server/visual_review_server.py | 本机推理脚本路径 | | VISUAL_REVIEW_PYTHON | python3 | 本机推理脚本的解释器 | | VISUAL_REVIEW_WORKSPACE | sandbox 工作区根 → 进程 cwd | 工作区根目录(.visual_review_tmp 所在处) | | VISUAL_REVIEW_ATTACH_ROOT | $HOME/.dsh/attachments/v1/objects | 附件对象存储根目录(/vr-image 兜底读取用) | | VISUAL_REVIEW_MODEL_DIR | HF 缓存默认路径 | 本机 Qwen3-VL 模型目录(worker 内读取) |

使用

  1. 直接体验:在聊天框粘贴上传一张图片 → 图片立即渲染在气泡里;模型侧自动出现附件注解,模型会自动调用 visual_review 并给出图片描述。
  2. 分析本地文件:让模型分析磁盘上的图片,例如“请用 visual_review 分析 /path/to/photo.png”,模型会以 image_path 参数调用工具。
  3. 定制提问:给模型指令时说明诉求,如“读出这张图片里的所有文字”“描述这个图表的趋势”。工具支持 prompt 参数,由模型按需传递。
  4. 切换引擎:调用 visual_review_config 修改云端配置即可;把三项都置空则回到本机引擎。

安全说明

  • /vr-image/api/session.prompt 路由只接受回环地址(127.0.0.1 / ::1)的请求,其他来源一律 403。
  • 云端 API Key 以明文存储在 $DSH_HOME/visual_review.config.json,请勿提交到仓库、注意权限控制。
  • 本机模式:图片仅在本机处理,不产生任何外部网络请求。

开发与测试

单独测试本机 worker(不经过 DSH)

# 方式一:环境变量指定模型目录
VISUAL_REVIEW_MODEL_DIR=/path/to/Qwen3-VL-8B-Instruct python3 -u server/visual_review_server.py

# 方式二:命令行参数指定模型目录
python3 -u server/visual_review_server.py /path/to/Qwen3-VL-8B-Instruct

另开一个终端发送请求(图片先 base64 编码):

B64=$(base64 -w0 examples/test_image.png)
printf '{"id":1,"kind":"describe","image_b64":"%s","prompt":"请描述这张图片","max_new_tokens":256}\n' "$B64" | \
  VISUAL_REVIEW_MODEL_DIR=/path/to/model python3 -u server/visual_review_server.py

预期依次收到 {"event":"ready"}{"id":1,"ok":true,"text":"..."}kind:"decode_image" 可用于把 base64 文件还原为二进制文件(无需模型)。

协议速查

| 方向 | 消息 | | --- | --- | | Host → worker | {"id":<n>,"kind":"describe","image_b64":"...","prompt":"...","max_new_tokens":<int>} | | Host → worker | {"id":<n>,"kind":"decode_image","b64_path":"...","out_path":"..."} | | worker → Host | {"id":<n>,"ok":true,"text":"..."}{"id":<n>,"ok":false,"error":"..."} | | worker → Host | {"event":"ready"}(模型就绪)/ {"event":"load-failed","error":"..."} |

常见问题(FAQ)

Q:模型加载很慢 / 报“模型加载超时(20 分钟)”。 本机模式首次要加载 Qwen3-VL-8B 权重,视磁盘与显存可能需数分钟。可先确认 VISUAL_REVIEW_MODEL_DIR 指向正确,或用云端模式。

Q:报“找不到附件 ID”。 附件引用只在本会话内有效:请直接重新上传图片,或改用 image_path 传入本地文件路径。

Q:云端调用失败,提示 url 似乎缺少 /chat/completions url 必须是完整的 OpenAI 兼容端点,如 https://xxx/v1/chat/completions

Q:图片在界面上显示为“(图片加载失败)”。 /vr-image 仅允许回环请求;若通过远程访问 DSH Web,图片渲染可能被拒绝。另外开发模式下修改客户端插件需要重建前端 bundle 并刷新。

Q:粘贴图片后模型说看不到图片。 确认宿主日志中有 /api/session.prompt 拦截路由已注册。若该行缺失(webServer/apiProxy 不可用),发送拦截被跳过,此时依赖 agent/pre-step 兜底;仍不行请重新上传图片。

License

MIT © visual-review authors


联系我们

欢迎关注公众号、加入交流群,获取最新动态、使用反馈与开源讨论:

| 公众号 · 关注获取最新动态 | 交流群 · 入群交流反馈 | | :---: | :---: | | | |

💡 群二维码有时效(7 天),过期后请关注公众号获取最新入群方式。