DiagramKit · dsh-tool-diagram
给 DeepSeek Harness (DSH) 用的结构化示意图插件:量准字宽、验准布局,每条问题连修法一起报回来。
English — A DeepSeek Harness plugin for drawing
structured diagrams from a declarative spec. It measures real font metrics (parses the TTF tables
itself), checks your hand-placed layout for overflow / overlap / edges crossing boxes / label
collisions, and returns the image plus a report where every issue carries an actionable fix.
13 primitives, ~80 ms per diagram at 300 dpi. Covers flowcharts, N-S & PAD diagrams, DFD, E-R,
UML use-case & class diagrams, decision trees, fault trees, org charts.
用例图
它解决什么问题
让 agent 画示意图,最费时间的不是"画",是不知道画对没有:框够不够宽?标签压没压线?
箭头穿框了吗?只能渲染出来、盯着看、再改——一轮四步。
DiagramKit 把这一轮压成一次调用:给你图,同时也给你一份结构化报告,每条问题都带修法。
自检发现 1 个错误:
[error] text_clipped node=cond lines=3 textH=1.06 boxInnerH=0.54 over=0.52
→ 「A+B>C 且 A+C>B 且 B+C>A ?」被折成 3 行、需要 1.42cm 高,但框只有 0.9cm。
把框高加到 1.42cm(或宽加到 3.46cm 让它一行放得下),或字号降到 4pt
照着改坐标就行,多数轮次不必再看图。
它不是自动排版引擎。 N-S 图的递归划分、PAD 图的左侧主线,这些布局是学科要求,
不该由算法替你决定。所以:at 给了就绝对定位,工具只负责量准和验准。
功能
三个工具
| 工具 | 做什么 |
|---|
diagram_create | 按 spec 画图,返回「内联图 + 自检报告 + 画布尺寸」 |
diagram_patch | 增量改图:move / moveby / resize / set / add / remove / canvas,不重发整个 spec |
diagram_measure | 只测量与自检,不渲染——想知道"这行字放不放得下"时用它,最便宜的一档 |
排版量尺:真解析字体,不靠估
自己解析 TTF/OTF 的 head / hhea / hmtx / cmap 四张表取 advance width,零依赖。
这件事在中文里有个容易翻车的地方:“”()《》,。 这些看着"小"的符号其实是全角 1 em。
把 输出“等边三角形” 里的弯引号当半角估,会少算 0.56 cm(22%)——框就装不下了。
顺带还有:
- 中文折行 + 禁则——不会让一行以
,。、)】 这类收尾标点开头
- 自动尺寸——不给
size 就按文字宽高加内边距算,也可以给 minSize 兜底
- 缺字检测——字体里没有的字符当场报
glyph_missing,而不是渲染出一堆方框
自检:10 类问题,每条都带修法
| 类型 | 级别 | 查什么 |
|---|
text_overflow | error | 文字比框宽(含不可断行的长串) |
text_clipped | error | 折行后高度装不下 |
node_overlap | error | 两个框叠在一起,并给出该挪多少 |
edge_through_node | error | 连线穿过第三个框 |
outside_canvas | error | 元素超出画布,并给出画布该放多大 |
glyph_missing | error | 字体缺字形 |
label_collision | warn | 标签互相压、或压住框里的文字 |
label_on_edge | warn | 标签压在连线上 |
edge_end_on_text | warn | 箭头落点压住框内文字或编号 |
near_miss | warn | 两个框贴得比 0.15 cm 还近 |
edge_cross | info | 连线交叉数(只统计,不一定要改) |
级别语义:error 一定难看/一定错;warn 能看但会扣分;info 供参考。
13 种图元
| shape | 画出来是什么 | 典型用途 |
|---|
rect | 直角矩形 | 外部实体、E-R 实体、PAD 处理框 |
round_rect | 圆角矩形 | DFD 加工 |
store | 开口矩形,编号在缺口外 | 数据存储 |
ellipse | 椭圆 | UML 用例、E-R 属性 |
diamond | 菱形 | E-R 联系 |
actor | 火柴人,名字在下方 | UML 参与者 |
class_box | 三分栏类框(\n---\n 分隔各栏) | UML 类图 |
and_gate / or_gate | 与门(下平上半圆)/ 或门(上圆下收尖) | 事故树 FTA |
box_span | 无边框,只占位和排文字 | N-S 图的"条件带""T/F 标记带" |
line_h / line_v | 单根线段 | N-S 图的分区线、PAD 图的主线 |
chevron | 分支符 < | PAD 图的条件分支 |
后四种是专为 N-S 图和 PAD 图加的。这两种图本质上不是"框 + 箭头",
而是"一块区域被反复切分",没有对应图元就只能退回写代码。
这些元素可以用 "structural": true 标成"版面骨架"——它们天然与别的元素共边、贴靠,
不参与重叠判定(否则 N-S 图会被报几十条"重叠")。
连线:四档精确度,从"随便连"到"我说了算"
| 手段 | 效果 |
|---|
| 什么都不给 | 两端自动求交,斜线 |
fromSide / toSide | 从指定边进出,自动夹在边内 → 得到水平/垂直线 |
fromPoint / toPoint | 锚点写死,最精确 |
waypoints | 整条折线自己给,工具完全不路由 |
labelAt | auto / above / below / left / right / [x, y] 手工定位 |
输出
- 一切以厘米为单位,画布尺寸直接就是 Word 插图的尺寸,不用再做 px→cm 换算
- PNG(默认 300 dpi,可调到 600)+ SVG
- 既可内联返回(图直接进对话),也可落盘到指定路径
- 支持
containers:系统边界框、泳道这类外框
安装
cd $env:USERPROFILE\.dsh\profiles\desktop
pnpm add github:erzhe-lume/dsh-tool-diagram
然后把 "dsh-tool-diagram" 加进同一个 package.json 的 dsh.profile.bundles 数组,重启 dsh:
"dsh": { "profile": { "bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dshmarket",
"dsh-tool-diagram" // ← 加这一行
] } }
首次安装会看到 [ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: sharp@0.34.0——可以忽略。
pnpm 11 默认拦下依赖的安装脚本,而 sharp 的原生二进制走 optionalDependencies,不依赖它。
想消掉警告执行 pnpm approve-builds。
本包自带组合包声明(dsh.bundle.patch),所以不需要动 profile 的 cordis.patch.yml。
想改默认参数的话,在那里写同 id 的行即可覆盖:
- id: tool-diagram
name: dsh-tool-diagram
config:
dpi: 300
maxDpi: 600
maxDiagrams: 32
不装 DSH 也能用
命令行入口是现成的,画图、导出、自检都不依赖 DSH:
node lib/cli.js examples\usecase.json --out usecase.png --dpi 300 # 画图 + 报告
node lib/cli.js examples\broken.json --measure # 只测量
node lib/cli.js examples\lib-dfd-l1.json --patch examples\patch-labels.json --out out.png
node lib/cli.js examples\usecase.json --out a.png --svg # 顺带导出 SVG
快速上手
一个最小例子——画两个加工和一个数据存储:
{
"canvas": { "w_cm": 12.0, "h_cm": 5.0 },
"nodes": [
{ "id": "p1", "shape": "round_rect", "num": "1", "text": "读卡与验证密码",
"at": [3.0, 1.4], "size": [3.4, 1.1] },
{ "id": "p2", "shape": "round_rect", "num": "2", "text": "取款处理",
"at": [8.6, 1.4], "size": [3.0, 1.1] },
{ "id": "db", "shape": "store", "num": "D1", "text": "中央数据库",
"at": [6.0, 3.9], "size": [4.0, 0.85] }
],
"edges": [
{ "id": "e1", "from": "p1", "to": "p2", "arrow": "open", "label": "验证通过" },
{ "id": "e2", "from": "p1", "to": "db", "arrow": "both", "label": "读 / 写" }
]
}
返回:
画布 12.00 × 5.00 cm;节点 3,边 2,连线交叉 0
自检通过:没有发现问题。
用时 84ms
PNG → usecase.png (1417×591px @ 300dpi, 33.8KB)
同时拿到内联的图、sizeCm: [12.0, 5.0](Word 里直接按这个宽度插)、以及后续
diagram_patch / diagram_measure 要用的 diagramId。
改图不用重画——按报告的建议打补丁:
[
{ "op": "move", "node": "db", "to": [6.0, 4.2] },
{ "op": "resize", "node": "p2", "size": [3.4, 1.1] },
{ "op": "set", "edge": "e2", "label": "读 / 写", "labelAt": "left" }
]
spec 速查
{
"canvas": { "w_cm": 15.6, "h_cm": 8.3 }, // 可省,省了按内容算
"style": { "preset": "se-textbook" }, // se-textbook | uml | dfd
"nodes": [
{ "id": "uc1", "shape": "ellipse", "text": "验证用户身份",
"at": [7.8, 3.35], // 中心点(厘米);给了就绝对定位
"size": [5.0, 1.8], // 可省,省了按文字算
"num": "1", // 编号(DFD 加工 / D1 数据存储)
"textAlign": "left", // left/right 时 at 变成锚点而不是中心
"fontPt": 8, "paddingCm": 0.18 }
],
"edges": [
{ "id": "e1", "from": "a1", "to": "uc1", "arrow": "none" },
{ "id": "e2", "from": "uc1", "to": "uc2", "arrow": "open", "dash": true,
"label": "<<include>>", "labelAt": "right" }
],
"containers": [
{ "id": "g1", "text": "图书管理系统登录模块", "at": [7.8, 6.4], "size": [10.4, 6.0],
"labelPos": "top_left" }
]
}
样式预设
| preset | 效果 |
|---|
se-textbook | 黑体 8pt / 标注 7pt / 线宽 1.2pt / 白底黑线——软件工程教材插图风格 |
uml | 同上,用例与参与者名字字号略调 |
dfd | 加工圆角与存储缺口按 DFD 惯例 |
字体走文件路径(默认 C:/Windows/Fonts/simhei.ttf),可以换成任意 TTF/OTF/TTC。
适用范围
| 档 | 图种 |
|---|
| 开箱即用 | 程序流程图、N-S 图、PAD 图、判定树、分层 DFD、E-R 图、UML 用例图/类图/状态图/活动图、系统架构图、部署图、组织架构图、WBS、业务流程图、泳道图、事故树、事件树、临床路径图、诉讼流程图、知识点结构图… |
| 加一两个图元 | UML 时序图(要生命线 + 时间轴)、甘特图(时间轴)、思维导图(放射布局)、数据结构指针图、鱼骨图 |
| 不适合 | 数据可视化(折线/柱状/散点/热力——它们的正确性在数据里,不在布局里)、电路原理图、机械制图、建筑平立剖、地图、解剖图、信息图 |
判断标准有三条,同时满足才值得用:① 离散元素 + 关系连线;② 有容器/层级;
③ 正确性判据是"连对没有、摆开没有",而不是"画得像不像实物"。
顺带一提:它只对中文做了折行与禁则优化(这是它的主场景);纯英文排版也能用,
但换行规则按空格断词,没有连字符断词。
更多文档
License
MIT