dsh-syntax-checker
Đã xác minh@kiwifruit/dsh-syntax-checker · v0.1.2 · MIT
Multi-language syntax checking service (JS/TS/YAML/Python): bracket matching, invisible chars, syntax errors, via Tree-sitter + Ruff
Cài đặt
dsh plugin add @kiwifruit/dsh-syntax-checker 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ẻ
Readme
DSH Syntax Checker
多语言语法检查服务(JS / TS / YAML / Python):括号匹配、不可见字符、语法错误检测与自动修复。
同一套引擎支持两种运行形态:
- DSH Cordis 插件(
@kiwifruit/dsh-syntax-checker)—— 由 DSH 宿主经纤程加载,向模型暴露syntax_check工具,并向其他插件提供syntaxChecker服务; - 独立 Node.js 服务 / 库 —— Fastify HTTP API(含 OpenAPI 文档),或
createSyntaxChecker()直接嵌入上游系统。
功能特性
| 能力 | 说明 |
|---|---|
| 括号匹配 | () / [] / {} / 字符串字面量内的括号不参与匹配 |
| 不可见字符 | 检测零宽空格、BOM、双向控制符等隐形陷阱 |
| 语法错误 | Tree-sitter 解析(JS/TS/YAML)+ Ruff(Python) |
| 行尾空白 | 通用规则 |
| YAML 专项 | 重复键、Tab 缩进 |
| 自动修复 | Ruff 诊断自带 fix.edits + 编辑应用器(行/列 → offset),多轮迭代收敛 |
技术栈
- 运行时:Node.js ≥ 20,ESM
- 解析:
web-tree-sitter(WASM 语法,位于assets/)+ruff(外部 CLI,Python 后端) - HTTP:Fastify 5 +
@fastify/swagger(OpenAPI 文档,openapi.yaml为导出产物) - 插件体系:
@deepseek-ai/cordis(纤程 / waterfall 事件)+@deepseek-ai/dsh-tools(defineTool) - 配置校验:
@deepseek-ai/schemastery(Standard Schema) - 质量门禁:TypeScript 5 严格模式 + ESLint 9 flat config + Vitest 4(覆盖率 v8)
快速开始
独立 HTTP 服务
npm install
npm run build
npm start # 生产:node dist/api/server.js
npm run dev # 开发:tsx src/api/server.ts
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /health |
健康检查(含 ruff 可用性探测) |
| POST | /api/v1/lint |
单文件语法检查 |
| POST | /api/v1/lint/batch |
批量检查(有上限,见 schemas.ts 的 MAX_BATCH_SIZE) |
| POST | /api/v1/fix |
自动修复,返回修复后源码 |
响应采用统一包装(code / message / timestamp / data),HTTP 状态码表达传输层状态,业务错误码在响应体中。完整契约见 openapi.yaml 或启动服务后访问 Swagger UI;错误码清单见 docs/error-codes.md。
作为库嵌入(独立模式)
import { createSyntaxChecker } from '@kiwifruit/dsh-syntax-checker';
const checker = createSyntaxChecker(undefined, {
timeoutMs: 30_000,
maxRetries: 2,
policies: { timeout: true, retry: true, observation: true },
});
const result = await checker.lint({
filePath: 'a.py',
sourceText: 'import os\nimport os\n',
});
// result.diagnostics / errorCount / warningCount / infoCount
独立模式无 Cordis 纤程,配置在此处经 Config schema 同步校验并填充默认值。
作为 DSH 插件安装
推荐安装:插件已发布到 npm(scoped 包
@kiwifruit/dsh-syntax-checker)。裸包名解析到latest,刚发版受 pnpm 24 小时最小发布年龄冷却限制——立即使用请写精确版本号(精确版本自动豁免冷却期)。
安装命令(--profile 是必选参数,指定目标配置文件,如 web / headless):
dsh plugin --profile web add @kiwifruit/[email protected]
<spec> 支持多种来源:
| 来源类型 | 命令格式 | 示例 |
|---|---|---|
| npm 包 | dsh plugin --profile web add <包名> |
dsh plugin --profile web add @kiwifruit/dsh-syntax-checker |
| 精确版本 | dsh plugin --profile web add <包名>@<版本> |
dsh plugin --profile web add @kiwifruit/[email protected] |
| GitHub 仓库 | dsh plugin --profile web add github:<owner>/<repo> |
dsh plugin --profile web add github:owner/dsh-syntax-checker |
| 本地目录(符号链接) | dsh plugin --profile web add link:<路径> |
dsh plugin --profile web add link:D:/Git/gitee/DSH-Syntax-Checker-main |
| 本地目录(复制安装) | dsh plugin --profile web add file:<路径> |
dsh plugin --profile web add file:./dsh-syntax-checker |
用
link:时需先npm run build(它不触发prepare,加载的是dist/),并在源码目录自备依赖(pnpm 不为link:依赖解析依赖)。
裸包名解析到 npm
latest,受 pnpm 24 小时最小发布年龄冷却限制——刚发版要立即安装,请写精确版本号(精确版本自动豁免冷却期)。
GitHub 来源须知(依据 DSH 官方构建陷阱,工具示例 第十二步):git install 拉取的是源码不是构建产物。本包已提供自包含的
prepare脚本(安装后自动tsc),但 pnpm ≥10 默认拒绝运行 git 依赖的 prepare 脚本,用户需在 profile 的pnpm-workspace.yaml中放行:allowBuilds: dsh-syntax-checker: true⚠️ 该放行等于授权安装时在沙箱外执行本包构建脚本,建议 pin commit(
github:owner/dsh-syntax-checker#<sha>)。更稳的方式是 npm 包 / tarball 安装(预构建产物,无需 allowBuilds)。
安装后生效链路:dsh plugin 是 pnpm 转发器 + bundle 自动登记,不是补丁合并——先 pnpm add 落包,再按已安装状态对账 dsh.profile.bundles(包的 manifest 声明 dsh.bundle 即登记进去),启动时由 bundle 层读取 cordis.patch.yml 参与分层组合。因此 profile 的 cordis.patch.yml 不必再写本插件条目。增删 bundle 后需重启 DSH 进程才生效(patchReload: live 只覆盖补丁层)。
安装后验证:
dsh --profile web --dump-config | tail -20 # syntax-checker 行是否进入组合树
然后启动 dsh --profile web,向模型确认 syntax_check 工具已出现在工具列表中(装配验证的两个信号:工具列表 + 服务就绪)。
升级:npm 来源与安装命令相同,再次执行 dsh plugin --profile web add @kiwifruit/dsh-syntax-checker 即升级;link: 来源改完源码 npm run build 即可。卸载:dsh plugin --profile web remove @kiwifruit/dsh-syntax-checker。
安全提醒:安装插件等同于运行第三方代码。安装前请查看插件源码,不熟悉的插件建议在隔离环境先测试。
插件装配清单(本地 loader 装配 / 开发态)
仓库根目录的 cordis.yml 即装配清单(格式遵循 约束/001接口/工具扩展.md §3.1–3.2),供本地 loader 加载;随包分发的 cordis.patch.yml 以 - insert: 语义携带同一条目,供 DSH 的 bundle 层读取。二者由 package.json 的 dsh.bundle.patch 串起来——该字段是 dsh plugin add 判定"本包是 bundle"的依据,据此登记进 dsh.profile.bundles:
- id: syntax-checker
name: '@kiwifruit/dsh-syntax-checker'
inject: [tools]
config:
timeoutMs: 30000
maxRetries: 2
verbose: false
policies: { timeout: true, retry: true, observation: true }
插件入口以原名导出 Cordis 契约:apply / name / inject / provide / Config。这是硬性前提——若只以别名导出,Cordis 会跳过 schema 校验与默认值填充(Config 缺原名时是静默跳过,故障在运行期才炸出)。
加载后:
- 向模型:注册
syntax_check工具(经defineTool,参数filePath/sourceText/language?/fix?); - 向其他插件:
ctx.provide('syntaxChecker', engine),消费方声明inject: ['syntaxChecker']即可调用lint/fix。
配置项
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
timeoutMs |
number | 30000 |
单次语法检查的超时预算(毫秒);单次调用可用 options.timeoutMs 覆盖 |
maxRetries |
number | 2 |
后端瞬时故障的最大重试次数 |
verbose |
boolean | false |
是否记录成功事件(默认只记录 fail / timeout) |
policies.timeout |
boolean | true |
超时伴生策略开关 |
policies.retry |
boolean | true |
重试伴生策略开关 |
policies.observation |
boolean | true |
观测伴生策略开关 |
cordis.yml的config是整行替换、非深度合并——覆盖时必须写全整个对象。 关闭某项策略后,可外接同名伴生插件替换它(策略可装卸,不重复注册)。
架构
三角色接缝
Definition(definition.ts) 抽象接口 + 事件词汇表 + 错误码
▲ │
│ 实现 │ 消费
Provider Consumer
├─ RuffBackend(Python) ├─ ParserEngine(中间层)
└─ TreeSitterBackend └─ syntax_check Tool / syntaxChecker 服务
(JS/TS/YAML)
事件模型(Cordis waterfall 语义)
syntax/check(waterfall):lint 的执行门。伴生策略通过它挂载横切逻辑:TimeoutPolicy以prepend注册,恒为最外层——保证「超时包住重试」,与插件加载顺序无关;RetryPolicy默认追加,位于链尾——waterfall 内部cbs.shift()共享游标,多次调next()的监听器若不在链尾,重试会跳过其后所有监听器;- 不调
next()即短路整条链(含默认行为)。
syntax/check-end(emit):检查结束通知(status: success | fail | timeout、耗时、诊断列表、traceId),观测策略经此记录结构化日志。
平台抽象(platform.ts)
PlatformContext 屏蔽「是否运行在 Cordis 宿主内」的差异:
- 有宿主:waterfall / emit / 日志 / 工具服务走真实 ctx;
- 无宿主:Node 等价实现回退;
- 宿主服务存在但抛错时同样回退(空字符串是合法返回值);
fs/bash在 cordis 4.0.2 上并非必需依赖,inject只声明['tools'],多声明会让纤程卡在 PENDING。
目录结构
src/
├── core/ # 领域核心:Diagnostic / Rule / Linter / Fixer / Errors / Language
├── rules/ # 规则实现:universal(括号、不可见字符…)、js-ts、yaml
├── parsers/ # 解析适配:tree-sitter-parser、ruff-runner(spawn + stdin)、ruff-adapter
├── plugin/ # Cordis 插件层
│ ├── definition.ts # 服务契约 + 事件词汇表(declare module 合并进 Cordis 类型)
│ ├── config.ts # Schemastery Config schema(Standard Schema)
│ ├── platform.ts # 宿主/独立双模式平台抽象
│ ├── engine.ts # ParserEngine 中间层(lint/fix 编排)
│ ├── providers/ # RuffBackend / TreeSitterBackend
│ ├── policies/ # Timeout / Retry / Observation 伴生策略
│ ├── tool.ts # syntax_check 工具(defineTool)
│ └── index.ts # 原名导出 apply / name / inject / provide / Config
├── api/ # Fastify 应用:路由、schema、统一错误处理、Swagger
└── index.ts # 库形态总出口(含别名导出,原名契约单列)
开发
npm run typecheck # tsc --noEmit
npm run lint # eslint src tests scripts
npm test # vitest run --coverage
npm run test:watch # vitest watch
npm run docs:openapi# 导出 OpenAPI 文档(代码为唯一真相源)
测试分两层:
tests/:core / rules / parsers / api 的单元与集成测试;tests/plugin/:插件层测试(事件门、平台回退、工具定义、装配——装配测试须打 dist 后测,避免「源码已修、产物漂移」的假绿)。
Python 相关用例需要本机可用 ruff,缺失时自动跳过。
已知边界
ruff fix子命令不存在,自动修复走ruff check --fix;exit ≥ 2 视为调用级失败。- Windows 下从
file://URL 取路径必须用fileURLToPath(URL.pathname会产生/D:/...坏路径)。 - Tree-sitter 的
Language.load接收Buffer而非ArrayBuffer。
文档索引
docs/error-codes.md—— 业务错误码清单docs/dsh-integration-plan.md/docs/integration-review.md—— DSH 集成方案与审查记录openapi.yaml—— API 契约导出产物- DSH 插件生态约束文档(装配清单格式、工具定义、事件语义)——本地工作区
约束/目录,未随本仓库发布
License
MIT