前言¶
让模型直接写 HTML 报告,最常见的失败方式不是抛异常,而是静默失效:类名是模型凭印象编的,页面打开后那一块没有样式;<head> 里漏了一条 <link>,组件类名全都对,但整段没样式;骨架层级写错,布局塌了,控制台也不报错。这三种情况的共同点是——没有人打开看一眼就不会被发现。
owain323/dsh-plugin-agentcss 就是冲着这三类问题来的。它是 DeepSeek Harness 的一个插件,维护者 owain323,社区目录 SkillHub 上归在「工作流」分类下(目录页显示当前 0 星),MIT 许可。它把 agentcss 这套报告页库包装成四个模型可以直接调用的工具:查组件、生成页面骨架、交付前自检、导出 PDF。
下面介绍这个插件的具体能力、安装方式和实际一轮的用法。
它解决什么¶
README 里把三个坑列得很清楚:
| 坑 | 现象 | 谁能发现 |
|---|---|---|
| 类名凭感觉编 | 页面不报错,只是那一块没样式 | 没人,直到人打开看 |
<head> 漏一条 <link> |
组件类名都对,但那部分完全没样式 | 没人,直到人打开看 |
| 骨架层级错 | 布局塌了,但不抛异常 | 没人,直到人打开看 |
已有的做法要么是让模型把整个库抄进页面(体积大、版本容易漂),要么是写完人工打开检查。这个插件选的是第三条路:让模型查库、按规则生成,然后的机器自检把上面三类问题拦在交付前。它明确不含组件定义,组件、令牌、判据全部来自 npm 上的 agentcss。
四个工具¶
插件注册的工具名字都以 agentcss_ 开头。四个工具对应「查得到、起得对、交得出去、发得出去」四步。
1、agentcss_catalog:写 HTML 之前调用。按关键词或者分层查组件,返回组件 id、所属分层、根类名、需要引入的样式表路径,以及一句话用途。需要额外组件时先用它查。
2、agentcss_new_page:新页面从这里开始,不要手写 <head>。返回一个自包含的目录,里面有 index.html 和 agentcss/(库样式表副本)。
3、agentcss_check:每次改完页面跑一次。返回结构化问题列表,每条带规则名、行号、级别和说明。
4、agentcss_pdf:内容定稿、要发出去或者要交给打印时用。返回 PDF 路径、页数、纸幅、字节数;如果有 JS 异常会点名。
agentcss_check 的检查项包括:类名在库里有没有、类名有但页面没引到定义它的样式表、图片缺不缺 alt、表头有没有 scope、标题有没有跳级、表单控件有没有可读名称、id 有没有重复。它是纯静态检查,不联网、不开浏览器。
agentcss_pdf 会起一次本机 Chrome/Edge,不开端口、不复用你的浏览器配置。导出顺序是库定死的:页面加载 → 字体就绪 → 可选可见元素 → 额外等待 → 定格动画 → 打印。失败或超出页数预算时,它不改写旧 PDF,也不替你截断内容——README 的说法是截断是静默丢东西,比报错停下危险得多。
安装与启用¶
安装命令直接来自 README。Harness 里「添加插件」有三个入口:npm 包名(推荐,版本随库走)、GitHub 地址、本地目录。命令行等价写法:
# 从 npm 装
dsh plugin --profile desktop add dsh-plugin-agentcss
# 或从 GitHub 装(跟踪 main)
dsh plugin --profile desktop add https://github.com/owain323/dsh-plugin-agentcss
装完需要重启 Harness,工具才会出现到模型的可调用列表里。
典型一轮¶
下面的流程取自 README 的例子:
用户:用 agentcss 做一份三季度营收分析页,放在 /work/reports/q3
模型 → agentcss_new_page({ dir: "/work/reports/q3", recipe: "report/finance" })
← 已生成 /work/reports/q3/index.html;样式表已复制到 …/agentcss
模型 写内容(需要额外组件就先 agentcss_catalog 查一下)
模型 → agentcss_check({ path: "/work/reports/q3/index.html", recipe: "report/finance" })
← 不通过:1 个 error
L42 error class-not-linked .bar 在库里,但这页没引 09-assets/bar/bar.css
模型 补一条 <link>,再跑一次 → 通过:0 error · 0 warn
要点是:不要先手写 <head> 和骨架,交给 agentcss_new_page 生成;内容写完用 agentcss_check 认一次账;要交付了再走 agentcss_pdf。dir 和 path 都必须传绝对路径,传错会明确报错,不会猜。
依赖与兼容¶
README 给的兼容表:
| 项 | 要求 |
|---|---|
| Node | >= 18(Harness 桌面版自带 24) |
agentcss |
^0.27.5 |
| Harness | 0.2.x 实测(0.2.2-rc.1) |
^0.27.5 这个下限不是随便选的。README 说明过半能力取决于库那一层:0.27.3 之前是灰底浅字;0.27.4 之前 .rep__fig 里的图没有宽度约束,一张 1920px 的截图会把整页撑破;0.27.5 才把仓库名与包名统一、站点根路径改 /agentcss/。这三件事在屏幕上都不显眼,要么打出来才知道,要么写进 URL 才知道。0.x 的 caret 范围只在同一个 minor 内,库出 0.28 时插件要跟着升一次。
另外两个刻意的选择值得知道:
- 不依赖任何
@deepseek-ai/*包。不用defineTool,直接用ctx.tools.register()注册裸定义。README 指出defineTool只是把参数编译成 JSON Schema 的包装器,二者等价,少一个 peer 依赖就少一整类版本解析故障。 - 不声明
engines.dsh。0.2.x 是预发布版,semver 的预发布规则会让>=0.2.0这类范围判不通过,安装直接被拒。
已知限制¶
1、dir / path 必须传绝对路径。写错会明确报错,不会猜。
2、建页时会把库样式表复制到页面旁边,约 340 KB、80 个文件。这是拿体积换自包含:页面双击就能打开,不发网络请求,发给别人也不会掉样式。
3、ai shot(横向溢出与 JS 报错的截图体检)还没接进来。README 明确说它是「看」的循环,与这里「写对 + 发出去」不是一条线。
4、PDF 是屏幕渲染结果。实体打印机的纸张、驱动缩放、双面、页眉页脚仍需人工打样一次,agentcss_pdf 不声称替你验过。
5、agentcss_new_page 默认不覆盖已有文件。目标 index.html 存在时默认拒绝,除非显式传 overwrite: true。
6、包本身只有约 700 行适配代码(含注释),没有任何组件定义。组件、令牌、判据全部来自 npm 上的 agentcss,agentcss_check 的类名白名单是从库的 CSS 现算的。README 解释了这样做的理由:复制一份组件树过来就等于同时存在两份真值,改一次 token 就开始不同步,两边各跑各的门禁,没人会发现。
适用场景与注意¶
适合的场景:用 Harness 写 HTML 报告页、想用一套既定组件库和版式、需要在人工打开之前做一次机器自检、需要把页面导出 PDF 发出去。
几点需要注意:
- 这个插件以当前 dsh 进程的权限运行。它能起本机 Chrome 导出 PDF,也能按绝对路径读写任意位置的文件。安装前先看一遍源码和许可证(MIT,包的
files里包含index.js、cordis.patch.yml、README.md、LICENSE)。 - 包的
dsh.bundle.patch指向cordis.patch.yml,说明安装时会对 Harness 的打包环节打补丁。这是插件自己做的适配,接第三方插件前值得先打开这个文件看一眼改了什么。 - 库是 0.x,
^0.27.5意味着 minor 升级会带来行为变化。升级插件时留意它声明的agentcss范围,不要单独把库升上去。 - 目录页(SkillHub)是社区站点,与 DeepSeek / 幻方无官方从属关系,也不代表这是官方应用商店条目。
- 需要人工兜底的地方:PDF 上机打样,以及「看一眼渲染出来对不对」这件事,插件目前不覆盖。
小结¶
这个插件的价值不在于多一个组件库,而在于它替模型建了一道交付前的闸门:页面骨架按规定生成,类名和样式表引用可以查、可以自检,自检不过就不收尾,PDF 失败宁可停下也不静默截断。它解决的是「不报错但不好看」这一类问题,这一类问题在没有这道闸门时只能靠人打开页面发现。
- 目录页:https://www.skillhub.cn/plugins/owain323/dsh-plugin-agentcss
- GitHub:https://github.com/owain323/dsh-plugin-agentcss