Chuyển đến nội dung chính

dsh-plugin-code-reviewer

Đã xác minh

dsh-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. 本地静态代码审查与工业协议解析工具插件。

Cài đặt

dsh plugin add dsh-plugin-code-reviewer

Xác nhận layer đã áp bằng dsh --profile default --dump-config — xem hướng dẫn cài plugin.

Mã nguồn

Phát hành lên npm mà không có repository công khai. Hãy kiểm tra nội dung package trước khi cài.

Thẻ

Tác giả

Readme

dsh-plugin-code-reviewer banner

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 — the next-tag line; npm latest is stale).
  • @deepseek-ai/cordis: ^4.0.1 (peerDependency — host provides it; types-only in code).

Pitfalls / 坑(从真实 spike 提炼,防呆)

  1. Node version: DSH requires Node ^22.19.0 || >=24.0.0. 旧版本只告警 EBADENGINE,建议升级。
  2. npm dist-tag trap (the big one): @deepseek-ai/dsh-tools latest 是过期的 0.0.1-rc.1,正确版本在 next tag(0.1.0-rc.x)。本脚手架已锁 next 版本,勿手动 npm i 覆盖。
  3. Version-line alignment: 所有 @deepseek-ai/dsh-* 包统一同一 0.1.0-rc.x 线,避免装两份模块。
  4. @deepseek-ai/cordis 是 peerDep:只 import type(编译期擦除),运行时 ctx 由宿主传入。
  5. Pure ESM:package.json 必须 "type": "module";tsc 用 module: esnext + moduleResolution: bundler
  6. dsh plugin add <dir> 的相对路径锚定调用目录——要在插件父目录执行。
  7. bundle 的 cordis.patch.ymlname 用包名(走 node_modules 解析),不要用相对路径。
  8. 注册是 effect:ctx.tools.register() 卸载自动清理;自己的资源(timer/连接)包 ctx.effect()
  9. 加载顺序靠服务依赖(inject),不靠文件顺序。
  10. 端到端(模型真正调工具)需 DEEPSEEK_API_KEY;无 key 时 --verify 只证明加载/列出。