dsh-plugin-code-reviewer
Verifieddsh-plugin-code-reviewer · v0.1.0 · MIT
3 local deterministic tools for DeepSeek Harness: code_review (14 static rules incl. OPC UA/Modbus/MQTT/serial/timeout), mqtt_probe (MQTT packet decoder), opcua_validate (NodeId validator). SCADA/MES/LIMS source scanner. 本地静态代码审查与工业协议解析工具插件。
Install
dsh plugin add dsh-plugin-code-reviewer Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Creators
Readme
dsh-plugin-code-reviewer
DeepSeek Harness 工具插件(由
create-dsh-plugin生成并定制)。 A DSH tool plugin — local deterministic code review for SCADA/MES/LIMS source. npm:dsh-plugin-code-reviewer· GitHub topic:dsh-plugin
三个工具,全部纯本地执行、不调用模型、无需 API key:
| 工具 | 作用 |
|---|---|
code_review |
对源码文件/目录做静态代码审查:14 条规则(通用 + 工业协议专属) |
mqtt_probe |
解析 MQTT 报文(十六进制输入):固定头/PUBLISH/CONNECT 深解 |
opcua_validate |
批量校验 OPC UA 节点地址(NodeId)语法,输出逐条 valid/reason |
📦 安装
npm i dsh-plugin-code-reviewer
dsh plugin --profile my-profile add dsh-plugin-code-reviewer
dsh --profile my-profile
# 看到: [dsh-plugin-code-reviewer] tools: code_review=true, mqtt_probe=true, opcua_validate=true
或本地开发模式:dsh plugin --profile my-profile add ./factory-tools(在插件父目录执行)。
🛠️ 工具一:code_review — 静态代码审查
规则(14 条)
| 规则 | 级别 | 说明 |
|---|---|---|
todo-marker |
low | TODO/FIXME/HACK/XXX 遗留标记 |
console-leftover |
medium | 残留调试输出(console.* / Console.WriteLine / Debug.WriteLine / printf) |
hardcoded-secret |
high | 硬编码 password/token/api_key 等凭据 |
hardcoded-ip |
low | 硬编码 IP(工业现场可能是合法 PLC/IPC 地址,需人工确认) |
sql-concat |
high | SQL 字符串拼接,疑似注入风险 |
eval-usage |
high | eval / new Function |
await-no-try |
medium | 有 await 但全文件无 try/catch(启发式) |
long-line |
low | 行超 120 字符 |
trailing-ws |
low | 行尾空白 |
opcua-address |
medium | 工业:OPC UA 节点地址格式错误 |
modbus-range |
medium | 工业:Modbus 地址越界(%MW>65535 / %MD>4294967295)或非标准段(2xxxx 保留、5xxxx+) |
mqtt-topic |
medium | 工业:MQTT 主题非法(空主题 / # 不在末尾) |
com-hardcode |
low | 工业:硬编码 COM 口 / SerialPort |
no-timeout |
medium | 工业:通信 API 无超时/取消机制(启发式) |
支持扩展名:.ts/.js/.tsx/.jsx/.mjs/.cjs/.py/.cs/.java/.go/.rs/.c/.h/.cpp/.hpp/.sql/.sh/.ps1/.vb;目录递归限深 4 层、最多 200 文件、最多 200 findings。
对话示例
用 code_review 审查 D:\mes\src 目录
→ 参数:path="D:\mes\src"(自动按扩展名扫描)
只审一个文件前 500 行:path="D:\mes\Program.cs", maxLines=500
真实输出(来自 demo/ 目录扫描)
{
"target": "D:\\...\\factory-tools\\demo",
"filesScanned": 2,
"findings": [
{ "file": "sample.cs", "line": 15, "severity": "high", "rule": "sql-concat",
"message": "疑似 SQL 字符串拼接,存在注入风险,建议改用参数化查询 / 预编译语句",
"snippet": "var sql = \"SELECT BatchNo, Qty, Status FROM dbo.Batch WHERE BatchId = \" + batchId;" },
{ "file": "plc_comms.cs", "line": 11, "severity": "medium", "rule": "opcua-address",
"message": "OPC UA 节点地址疑似格式错误(合法形态:ns=2;s=Temperature / ns=1;i=85 / nsu=<uri>;i=2)",
"snippet": "private const string NodeId = \"ns=2;Temperature\";" },
{ "file": "plc_comms.cs", "line": 14, "severity": "medium", "rule": "modbus-range",
"message": "Modbus 地址 %MW200000 超出范围(%MW ≤ 65535,%MD ≤ 4294967295)", "snippet": "…" }
],
"summary": "扫描 2 个文件,发现 14 个问题(1 high / 8 medium / 5 low)。详见 findings。"
}
📡 工具二:mqtt_probe — MQTT 报文解析
解析固定头(类型/DUP/QoS/RETAIN/剩余长度变长编码);PUBLISH 深解主题、报文 ID、负载;CONNECT 深解协议名/级别/连接标志/保活/ClientId。
对话示例
解析这段 MQTT 报文:10 10 00 04 4D 51 54 54 04 02 00 3C 00 04 64 65 6D 6F
→ 参数:hex="10 10 00 04 4D 51 54 54 04 02 00 3C 00 04 64 65 6D 6F"
真实输出(CONNECT 报文)
{
"valid": true, "packetType": 1, "packetTypeName": "CONNECT",
"flags": { "dup": false, "qos": 0, "retain": false },
"remainingLength": 16, "remainingLengthBytes": 1,
"protocolName": "MQTT", "protocolLevel": 4, "keepAlive": 60, "clientId": "demo",
"summary": "类型=CONNECT(1) · 剩余长度=16 · DUP=false QoS=0 RETAIN=false · 协议=MQTT v4 保活=60s ClientId=\"demo\""
}
非法/截断输入返回 error 字段(invalid-hex / too-short / truncated / bad-remaining-length)。
🔤 工具三:opcua_validate — OPC UA 节点地址校验
批量校验 NodeId 语法:ns=<数字>; / nsu=<uri>; + s=/i=/g=/b=,可选 svr= 前缀;裸标识符按 ns=0 补全。
对话示例
校验这些节点地址:
ns=2;s=Temperature
ns=2;Temperature
ns=1;i=85
ns=2;i=abc
真实输出
{
"ids": [
{ "id": "ns=2;s=Temperature", "valid": true, "normalized": "ns=2;s=Temperature" },
{ "id": "ns=2;Temperature", "valid": false, "reason": "缺少标识符类型(应为 s=/i=/g=/b= 开头)" },
{ "id": "ns=1;i=85", "valid": true, "normalized": "ns=1;i=85" },
{ "id": "ns=2;i=abc", "valid": false, "reason": "i= 需要整数,实际 \"abc\"" }
],
"validCount": 2, "invalidCount": 2, "summary": "共 4 条:合法 2,非法 2。"
}
🧪 自检 / Self-test
npm run build
node test/selftest.mjs # 21 项断言:三工具注册/输出结构/解析正确性
开发 / Development
npm install
npm run build # tsc → dist/index.js (pure ESM)
npm test # build + selftest(发布前自动执行 prepublishOnly)
Dependencies pinned / 依赖锁定
@deepseek-ai/dsh-tools:0.1.0-rc.6(exact — thenext-tag line; npmlatestis stale).@deepseek-ai/cordis:^4.0.1(peerDependency — host provides it; types-only in code).
Pitfalls / 坑(从真实 spike 提炼,防呆)
- Node version: DSH requires Node ^22.19.0 || >=24.0.0. 旧版本只告警 EBADENGINE,建议升级。
- npm dist-tag trap (the big one):
@deepseek-ai/dsh-toolslatest是过期的 0.0.1-rc.1,正确版本在nexttag(0.1.0-rc.x)。本脚手架已锁 next 版本,勿手动npm i覆盖。 - Version-line alignment: 所有
@deepseek-ai/dsh-*包统一同一 0.1.0-rc.x 线,避免装两份模块。 @deepseek-ai/cordis是 peerDep:只import type(编译期擦除),运行时 ctx 由宿主传入。- Pure ESM:package.json 必须
"type": "module";tsc 用module: esnext+moduleResolution: bundler。 dsh plugin add <dir>的相对路径锚定调用目录——要在插件父目录执行。- bundle 的
cordis.patch.yml里name用包名(走 node_modules 解析),不要用相对路径。 - 注册是 effect:
ctx.tools.register()卸载自动清理;自己的资源(timer/连接)包ctx.effect()。 - 加载顺序靠服务依赖(inject),不靠文件顺序。
- 端到端(模型真正调工具)需
DEEPSEEK_API_KEY;无 key 时 --verify 只证明加载/列出。