🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

视觉模型桥接 aijunjiang/dsh-plugin-vision

DeepSeek Harnessv0.1.0
aijunjiang13 天前有提交已提供中文文档扫描:含敏感能力

让纯文本 agent 借视觉模型看懂会话图片

29.4/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/31 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:npm 同名包「dsh-plugin-vision」归属 huyang218/dsh-plugins,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add aijunjiang/dsh-plugin-vision
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · vision
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-plugin-vision」归属 huyang218/dsh-plugins,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-plugin-vision @ 0.1.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/22 08:28:19

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 24 处,展示前 24 条)
  • 读取本地文件
    index.js:357
    const bytes = await readFile(join(dshHome(), 'attachments', 'v1', 'objects', hex.slice(0, 2), hex))
  • 读取本地文件
    index.js:371
    entries = await readdir(bucket)
  • 读取本地文件
    index.js:377
    const bytes = await readFile(join(bucket, hit))
  • 发起网络请求
    index.js:399
    response = await fetch(url, { signal })
  • 读取本地文件
    index.js:456
    const bytes = await readFile(path)
  • 发起网络请求
    index.js:1141
    response = await fetch(`${baseUrl}/chat/completions`, {
  • 读取本地文件
    ingest.js:64
    const existing = (await readFile(file, 'utf8')).trim()
  • 写入本地文件
    ingest.js:70
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    ingest.js:71
    await writeFile(file, `${token}\n`, { mode: 0o600 })
  • 写入本地文件
    ingest.js:148
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    ingest.js:150
    await writeFile(join(dir, `${hex}.json`), `${JSON.stringify(entry, null, 2)}\n`)
  • 读取本地文件
    ingest.js:163
    names = await readdir(dir)
  • 读取本地文件
    ingest.js:172
    const entry = JSON.parse(await readFile(file, 'utf8'))
  • 删除本地文件
    ingest.js:174
    await unlink(file)
  • 删除本地文件
    ingest.js:180
    await unlink(file)
  • 读取本地文件
    ingest.js:197
    names = await readdir(dir)
  • 读取本地文件
    ingest.js:205
    const entry = JSON.parse(await readFile(join(dir, name), 'utf8'))
  • 读取本地文件
    ingest.js:220
    const names = await readdir(join(dshHome(), META_DIR, 'items'))
  • 发起网络请求
    oss.js:220
    response = await fetch(url, { method: 'DELETE', signal: options.signal })
  • 写入本地文件
    oss-cleanup.js:59
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    oss-cleanup.js:60
    await writeFile(join(dir, fileNameFor(entry.key)), `${JSON.stringify(entry, null, 2)}\n`)
  • 读取本地文件
    oss-cleanup.js:71
    names = await readdir(dir)
  • 读取本地文件
    oss-cleanup.js:79
    out.push(JSON.parse(await readFile(join(dir, name), 'utf8')))
  • 删除本地文件
    oss-cleanup.js:94
    await unlink(join(pendingDir(), fileNameFor(key)))
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/schemastery@deepseek-ai/dsh-settings@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 内置11个服务商预设
  • 分析聊天中的图片
展开完整介绍(148 字)↓

给 DSH 智能体装上眼睛,接任意 OpenAI 兼容的视觉模型——内置 11 个服务商预设(豆包/Qwen-VL/GLM-V/OpenAI/Gemini/Ollama……),勾选能力项即可注入实时提示词引导,还能分析用户拖进聊天的图片;智能体自己写观察提示词,base64 永不进入它的上下文。

README

由 DeepSeek 最新模型翻译生成
dsh-plugin-vision English · 简体中文 给 DSH 的 agent 装一双眼睛。 主模型是纯文本的时候,会话里的图片对它来说只是一行 [image omitted because this model accepts text only; attachment sha256:1a2b3c4d]。 这个插件把那道缺口补上:agent 自己写观察指令,把图片交给在线视觉大模型(VLM)去看,拿回文字结论。 - 多供应商:统一按 OpenAI 兼容的 POST {baseUrl}/chat/completions 调用,内置 11 家预设,也可填任意自定义 endpoint。 - 能力勾选即提示词:在设置卡片里勾选该模型的特色能力(检测框 / OCR / 文档图表 / 视频 / GUI / 深度思考 / 多图对比…),这些说明会实时注入 agent 的系统提示,告诉它「这台模型还能干什么、该怎么提要求」。 - 提示词归 agent:插件不预置「请描述这张图片」之类的模板。观察什么、要多细、输出什么格式,由 agent 现场撰写。 - 看得见会话里的图:用户在输入框上传的图片,agent 可以直接用 latest 或占位符里那串 8 位摘要点名分析。
展开完整文档(README 剩余 1 节)
dsh-plugin-vision

English · 简体中文

给 DSH 的 agent 装一双眼睛。

主模型是纯文本的时候,会话里的图片对它来说只是一行 [image omitted because this model accepts text only; attachment sha256:1a2b3c4d]。
这个插件把那道缺口补上:agent 自己写观察指令,把图片交给在线视觉大模型(VLM)去看,拿回文字结论。

- 多供应商:统一按 OpenAI 兼容的 POST {baseUrl}/chat/completions 调用,内置 11 家预设,也可填任意自定义 endpoint。
- 能力勾选即提示词:在设置卡片里勾选该模型的特色能力(检测框 / OCR / 文档图表 / 视频 / GUI / 深度思考 / 多图对比…),这些说明会实时注入 agent 的系统提示,告诉它「这台模型还能干什么、该怎么提要求」。
- 提示词归 agent:插件不预置「请描述这张图片」之类的模板。观察什么、要多细、输出什么格式,由 agent 现场撰写。
- 看得见会话里的图:用户在输入框上传的图片,agent 可以直接用 latest 或占位符里那串 8 位摘要点名分析。
- 开发机直接推图:宿主机挂一条接收端点,局域网里任意开发机用一条 curl 把图片推上来即可, 不需要安装任何东西、不需要开放端口,也不用再把图先拷到宿主机磁盘。
- 密钥进凭据库:API Key 存在 ~/.dsh/.credentials.yaml,界面只显示「已配置 / 未配置」,永不回显字面量。
- 界面双语:设置卡片跟随 DSH 自身的语言设置切换(中文 / English)。

安装

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

⚠️ 不要执行 dsh plugin add dsh-plugin-vision。 这个裸包名会去公共 npm registry 解析,而
npm 上的 dsh-plugin-vision 是另一位作者的无关项目,不是本插件,且与当前版本的 DSH 不兼容。
请始终从本仓库安装。

dsh plugin --profile web add github:aijunjiang/dsh-plugin-vision
或从本地检出安装:dsh plugin --profile web add <本仓库路径>

内部 @deepseek-ai 依赖全部走 DSH 基线的可选 peer,npm 一个包都不会拉;声明了 dsh.bundle 的包会自动注册进 profile 的 bundles 层。
卸载:dsh plugin --profile web remove dsh-plugin-vision。

装完重启一次 dsh web,设置卡片才会出现。

方式 B:本地开发热装载

把仓库以包名链接进目标 profile 的 node_modules,再在该 profile 的 cordis.patch.yml 里插一行:

Windows(web profile 为例) New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-plugin-vision" -Target "C:\path\to\dsh-plugin-vision"

~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: vision-bundle
name: dsh-plugin-vision
config:
provider: ark
apiKeyEnv: ARK_API_KEY

web profile 是 live-reload:保存补丁文件,配置改动(供应商、模型、baseUrl…)立刻生效,不用重启。
但 插件源码(index.js / catalog.js)的改动不会热更——模块被 ESM 缓存住了,改完要重启 dsh web。
设置卡片属于客户端半,需要刷新一次页面;首次安装后如果卡片没出现,重启 dsh web 即可。

⚠️ Windows 上改这个 YAML 千万别用 PowerShell 5.1 的 Get-Content / Set-Content -Encoding utf8:前者按 GBK 解码会毁掉中文注释,后者会写入 BOM,两者都会让整个补丁层解析失败、所有插件一起掉线。
用 [System.IO.File]::ReadAllText/WriteAllText($p, $t, (New-Object System.Text.UTF8Encoding($false)))。

配置

设置 → 插件 → 视觉能力。

| 项 | 说明 |
| 供应商 | 切换即带出该家的默认 endpoint、模型与能力勾选 |
| 模型 ID | 留空 = 用预设模型。模型 ID 会随厂商迭代变化,过期了就在这里改 |
| Base URL | 留空 = 用预设 endpoint;私有部署 / 代理在这里填 |
| API Key | 写进 DSH 凭据库;留空表示不改动已存密钥 |
| 特色能力 | 勾选项注入 agent 系统提示;不勾就不会告诉 agent 该模型有这个本事 |
| 高级 → 细节档位 | auto / high(看小字更准)/ low(更快更省) |
| 高级 → 深度思考 | 不传 / auto / enabled / disabled,仅对支持的供应商生效 |
| 高级 → 单次最多图片数 | 默认 6 |
| 高级 → 超时(毫秒) | 默认 120000 |
| 高级 → 凭据引用名 | 密钥在凭据库里的键名,也可直接 export 同名环境变量 |

密钥解析顺序:设置里的 apiKey 字段 → DSH 凭据域(apiKeyEnv 指向的引用)→ 同名环境变量。

内置供应商预设

| id | 供应商 | 默认 endpoint | 默认模型 |
| ark | 火山方舟(豆包 Doubao) | https://ark.cn-beijing.volces.com/api/v3 | doubao-seed-1-6-vision-250815 |
| dashscope | 阿里百炼(通义千问 Qwen-VL) | https://dashscope.aliyuncs.com/compatible-mode/v1 | qwen3-vl-plus |
| zhipu | 智谱 BigModel(GLM-V) | https://open.bigmodel.cn/api/paas/v4 | glm-4.6v |
| openai | OpenAI | https://api.openai.com/v1 | gpt-4o |
| gemini | Google Gemini(OpenAI 兼容端点) | https://generativelanguage.googleapis.com/v1beta/openai | gemini-2.5-flash |
| moonshot | 月之暗面 Kimi | https://api.moonshot.cn/v1 | kimi-k3 |
| stepfun | 阶跃星辰 StepFun | https://api.stepfun.com/v1 | step-1o-turbo-vision |
| siliconflow | 硅基流动 SiliconFlow | https://api.siliconflow.cn/v1 | Qwen/Qwen2.5-VL-72B-Instruct |
| openrouter | OpenRouter(聚合) | https://openrouter.ai/api/v1 | qwen/qwen2.5-vl-72b-instruct |
| ollama | 本地 Ollama / vLLM(OpenAI 兼容) | http://127.0.0.1:11434/v1 | qwen2.5vl:7b |
| custom | 自定义(任意 OpenAI 兼容服务) | (自己填) | (自己填) |

预设是起点不是牢笼:任何一家的 endpoint / 模型都能在卡片里改。模型 ID 更新很快,以厂商文档为准。

agent 怎么用

vision_analyze

| 参数 | 必填 | 说明 |
| images | ✅ | 图片来源数组 |
| prompt | ✅ | 观察指令,由 agent 自己撰写 |
| system | | 给 VLM 的角色设定 |
| model | | 临时覆盖本次模型 |
| detail | | auto / high / low |
| thinking | | auto / enabled / disabled |
| max_tokens | | 本次回复上限 |

images 每一项可以是:

| 写法 | 含义 |
| C:\pic\a.png、/home/u/a.jpg | 本地文件;经 ctx.fs 读取,尊重沙箱与远端路由;无扩展名也能按魔数识别 |
| https://… | 远程 URL,原样交给 VLM 自己抓 |
| data:image/png;base64,… | 直传 |
| json:/路径/bundle.json | JSON 图包:base64 存在文件里,一次可带多张,见下节 |
| sha256:1a2b3c4d | 会话附件摘要,支持前缀——文本模型占位符里那 8 位就够 |
| latest / latest:3 | 本会话最近上传的 1 张 / 3 张图 |

vision_list_images

无参数。列出当前会话里出现过的全部图片附件(名称、尺寸、类型、摘要),以及接收端点 inbox 里由开发机推送上来的图(新→旧,带推送时间与过期时间),让 agent 在只看到 [image omitted …] 时也知道有哪些图可看、该点名哪一张。

⚠️ inbox 里的图不在会话事件里,latest 取不到它们——必须用 sha256 摘要点名。

局域网推图:开发机不用再中转

开发机是多台、环境各异、随时在变的。以前的做法是「先把图弄到宿主机磁盘,再传路径」——每换一台机器就要重来一遍。现在宿主机挂一条 HTTP 路由,任何开发机用一条 curl 把字节推上来即可,不需要安装任何东西、不需要开放任何端口。

一次推送

宿主机地址就是你打开 GUI 的那个地址;令牌见「设置 → 插件 → 视觉能力 → 推图端点」
curl -T shot.png \
-H "Authorization: Bearer <token>" \
"http://<宿主机>:3080/dsh-vision/ingest?name=shot.png"

返回:

{
"ok": true,
"id": "sha256:c414cd0e204d…", "digest": "c414cd0e204d", "mediaType": "image/png", "width": 640, "height": 480, "expiresAt": "2026-10-23T05:23:23.773Z", "usage": "vision_analyze images=[\"sha256:c414cd0e204d\"]" }

usage 是可以直接复制给 agent 的调用,图不进 agent 的上下文,只花掉这一行摘要。

端点约定

| 项 | 值 |
| 路径 | /dsh-vision/ingest,与 GUI 同端口(默认 3080) |
| 方法 | POST / PUT,请求体就是原始图片字节(不是表单,不是 base64 字符串) |
| 认证 | Authorization: Bearer <token>,也接受 X-Vision-Token: <token> |
| 命名 | ?name=xxx.png 可选,只作显示用 |
| 支持格式 | PNG / JPEG / WebP / GIF / BMP(按魔数判定,不信任 Content-Type) |

令牌从哪来

首次启动时自动生成,保存在 ~/.dsh/vision-inbox/token(权限 0600), 重启后复用同一个,所以开发机上的脚本写死一次就行。

| 状态码 | 含义 |
| 201 | 入库成功 |
| 401 | 令牌缺失或错误(两者响应一致,避免探测) |
| 413 | 超过单次体积上限(默认 32 MB) |
| 415 | 请求体不是受支持的图片 |
| 507 | inbox 已满(默认 200 条),先清理或调大上限 |
| 404 | 端点在设置里被关闭了 |

为什么服务在宿主机、而不是开发机

因为真正需要「看见」图片的是宿主机上的视觉模型(baseUrl 指向公网 DashScope / 方舟)。
把服务放开发机上,宿主机仍然得去拉;放宿主机上,开发机只需推一次。
开发机数量再多、环境再杂,都只影响「谁推」,「怎么收」只有一处。

存储与过期

- 字节走 DSH 现有的附件服务(attachments.saveImage),内容寻址、自动去重—— 同一张图重复推送不会多占一条。
- 元数据存在 ~/.dsh/vision-inbox/items/,默认 24 小时后由后台清理(每 10 分钟扫一次)。
- 清理只删元数据,不删附件对象——避免删掉会话里还在引用的图。

相关设置

| 设置项 | 默认 | 说明 |
| 推图端点 | 开 | 关掉后该路径返回 404 |
| 保留时长(小时) | 24 | ingestTtlHours |
| 单次体积上限 | 32 MB | ingestMaxBytes |
| inbox 条目上限 | 200 | ingestMaxItems,满了返回 507 |

⚠️ 3080 默认绑 0.0.0.0 且平台层没有鉴权。这个端点的令牌校验、体积上限、条目上限全部由插件自己实现,不要把令牌贴到公开的地方;不确定时把「推图端点」关掉即可。

传图纪律(已写进 agent 的系统提示,并在运行时强制)

| 别这么干 | 该这么干 | 为什么 |
| 起个本地/局域网图片服务,把 http://192.168.1.7/a.png 交给在线模型 | 直接把本地路径写进 images | 在线 VLM 在公网,它回不到你的内网。插件会在发请求前拦下私有地址(127.0.0.1 / localhost / 10.x / 192.168.x / 172.16–31.x / 169.254.x / .local)并告诉 agent 怎么改 |
| 把远端设备上的路径直接丢给模型 | 先取回本地,再传本地路径 | 远端主机的本地路径对公网模型同样不可达 |
| 自己 read 出 base64 拼成 data URL 传进来 | 传路径,或用 sha256: 摘要 / latest 点名 | 那串字节会完整落进 agent 的上下文,既挤占上下文又白花 token;插件读同一张图不占 agent 一个 token。真塞了大段 base64(≥20000 字符)时,工具会在结果末尾提醒它下次换传法 |

例外:当 baseUrl 本身就指向本机模型(Ollama / vLLM)时,模型与图片在同一张网里,私有地址是合法的,插件不会拦。

JSON 图包:手里只有 base64 时的正道

有时确实拿不到文件——远端 API 返回的、数据库字段里的、脚本现算的。这时不要让 agent 把 base64 打印出来,而是在产生它的那一侧写成 JSON 文件,agent 只传一行路径:

{
"images": [
{ "name": "首帧", "data": "iVBORw0KGgoAAAANSUhEUg..." }, { "name": "尾帧", "data": "iVBORw0KGgoAAAANSUhEUg..." } ] }

images: ["json:/tmp/bundle.json"] 整包
images: ["json:/tmp/bundle.json#2"] 只要第 2 张
images: ["json:/tmp/bundle.json#2-4"] 第 2 到第 4 张

省了多少:实测 3 张 200×150 的 PNG,

| | 字符数 | 约合 token |
| 拼成 data URL 走 images | 297,373 | ~74,000 |
| json:/tmp/bundle.json | 75 | ~20 |

模型收到的图一模一样,省掉的是 agent 上下文里那份副本。

解析器刻意写得宽松(Postel 原则),下面这些生产方写法都认:

| 位置 | 接受的写法 |
| 顶层 | {"images":[…]}、{"items"/"list"/"data"/"frames":[…]}、顶层直接是数组、单张时直接一个对象 |
| 条目 | 对象,或直接一串 base64 字符串 |
| 图片字段 | data / base64 / b64 / content / bytes / image / dataUrl;值可带 data:image/...;base64, 前缀、可带换行、可是 URL-safe base64 |
| 替代来源 | path(相对路径按 JSON 文件所在目录解析)或 url(同样受私有地址拦截约束) |
| 类型 | mediaType / mime / type 等可以完全省略——插件按字节魔数嗅探;声明错了以嗅探为准,并在标签里标注 |
| 名字 | name / label / title / id 等,会写进图片标签,方便在 prompt 里用「第 2 张」指代 |

生产方一行就能写出来:

远端:把当前目录若干 PNG 打成图包
python3 -c "
import base64, glob, json
print(json.dumps({'images':[{'name':p,'data':base64.b64encode(open(p,'rb').read()).decode()} for p in sorted(glob.glob('.png'))]}))
" > bundle.json

// Node:把内存里的 Buffer 直接落盘成图包
fs.writeFileSync('bundle.json', JSON.stringify({
images: buffers.map((b, i) => ({ name: frame-${i}, data: b.toString('base64') })),
}))

约束:单图仍受单图字节上限约束,展开后的总张数仍受单次最多图片数约束,整包读取上限 128MB;图包里不能再引用另一个图包(禁止套娃)。

坐标纪律

任何涉及位置的问题,都要在 prompt 里写死输出格式并要求模型回报它处理的图像宽高,否则坐标无法还原:

只输出 JSON:[{"label":"...","bbox_2d":[x1,y1,x2,y2]}] 并在 JSON 前用一行说明你处理的图像像素宽高,以及坐标是绝对像素还是归一化值。

各家约定并不一致(已知:Qwen-VL 返回处理后图像的绝对像素 bbox_2d;GLM-V 返回 0–1000 归一化 且包在 <|begin_of_box|> … <|end_of_box|> 里),所以「让模型自报基准」比「假设某种基准」可靠。

排错

| 现象 | 原因 / 处理 |
| 未配置视觉模型 API Key | 卡片里保存密钥,或 export apiKeyEnv 指定的环境变量 |
| HTTP 401 AuthenticationError | 密钥取到了但不被该 endpoint 认可——注意「搜索 API 密钥」和「模型 API 密钥」通常不是同一把 |
| HTTP 404 / model not found | 模型 ID 过期或该账号无权限,在卡片里换一个 |
| 只有思考内容、没有正文 | 思考型模型把 token 全花在推理上了:调大 max_tokens,或把 thinking 设为 disabled |
| 按摘要 xxx 没找到附件对象 | 先调 vision_list_images 确认摘要;跨会话的图不在当前会话事件里 |
| 字节不是受支持的图片格式 | 只支持 PNG / JPEG / WebP / GIF / BMP |
| 卡片不出现 | 客户端半需要刷新页面;仍无则重启 dsh web |
| 所有插件一起消失 | 多半是 profile 的 cordis.patch.yml 被写坏(BOM / 编码),见上文警告 |

开发

npm run sync # 用 catalog.js 重新生成 client.js 里的 CATALOG 镜像
npm test # 宿主逻辑 + 执行路径 + 卡片离线渲染(不开浏览器)
npm run check # 语法检查 + 校验镜像同步 + 跑全部测试

- catalog.js —— 供应商与能力清单,唯一真相源。加一家供应商只改这里,然后 npm run sync。
- index.js —— 宿主半:两个工具、配置命名空间、密钥解析、图片解析、动态系统提示段落,以及接收端点的挂载点。
- ingest.js —— 局域网接收端点:令牌、体积/条目上限、内容寻址入库、TTL 清理。自我封闭,不依赖 DSH 服务(attachments 走可选读取)。
- client.js —— 客户端半:设置卡片与它的 zh / en 词典。客户端 bundle 不允许 import,故 CATALOG 以生成的方式内联。
- tests/session-images.test.mjs —— 会话图片枚举(latest / 摘要点名的地基):覆盖宿主 session-controller 走的全部五条事件路径(data.content、data.message.content、data.inserted[]、 assistant/chunk 的 block-end、嵌套 tool-result),外加去重、顺序、脏数据与配置归一化、提示词注入。
- tests/execute.test.mjs —— 起一个本地 OpenAI 兼容假端点,把 execute() 完整跑通:断言请求体(鉴权头、各家 detail/thinking 映射、多图标注、extraBody 合并)与全部响应/错误分支(分片 content、思考截断、只有思考没有正文、模型拒答、HTTP 500、非 JSON、缺 Key、张数超限、中止)。
- tests/client-card.test.cjs —— 用 react-dom/server 把卡片渲染成静态 HTML,断言官方卡片结构、中英两种语言、zh/en 键集对齐、高级选项默认收起,以及保存设置与写凭据的调用序列。
- tests/ingest.test.mjs —— 接收端点:真起一个 http server 用真请求打,覆盖令牌校验(缺失/错误响应一致)、方法、格式、体积上限、条目上限、内容寻址去重、TTL 清理、坏文件容错、令牌持久化。

ingest.test.mjs 只依赖 node:*,不需要 DSH 的 node_modules,因此永远会跑;另外两个会在依赖缺失时自动跳过(退出码 0):index.js 需要 @deepseek-ai/schemastery,卡片测试需要 react / react-dom(浏览器端由 DSH 平台注入,本地可从 DSH profile 的 node_modules 解析)。

想在没有真实密钥时联调?

起一个 OpenAI 兼容的假端点,把 baseUrl 指过去、apiKey 随便填,就能验证请求体与全链路:

// mock.cjs —— 收到什么就落盘什么,然后回一段固定答复
require('node:http').createServer((req, res) => {
const chunks = []
req.on('data', c => chunks.push(c))
req.on('end', () => {
require('node:fs').writeFileSync('last-request.json', Buffer.concat(chunks).toString())
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ choices: [{ message: { content: 'MOCK OK' }, finish_reason: 'stop' }] }))
})
}).listen(8791, '127.0.0.1')

License

MIT
预览分享卡片长什么样 ↓aijunjiang/dsh-plugin-vision
分享 · DeepSeek Harness Hub
aijunjiang/dsh-plugin-vision

让纯文本 agent 借视觉模型看懂会话图片

这是你的仓库?认领条目

回到顶部