JMESPath 子集 JSON 查询。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:omdsh-dev/dsh-tool-json
GitHub 来源的插件在安装时会在你的机器上执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
DSH JSON 查询工具插件 —— JMESPath-inspired 路径查询(自定义子集),零依赖递归下降解析器。
为什么需要
Agent 处理 JSON 是高频操作——API 返回值、配置文件、工具输出到处都是 JSON。当前做法是起 bash 进程跑 node -e 或 jq,每次都有进程开销和字符串序列化成本。
DSH 内置 grep 可以做正则匹配,但无法理解 JSON 结构。对于 {"items":[{"id":1}]}:
grep只能做字符串级搜索,容易误匹配值、key、或嵌套子对象中的同名 keyjson走结构化路径,只匹配指定路径,不混淆 key 和 value
安全模型
手写递归下降解析器,无 eval/new Function;Object.hasOwn 防原型链污染(constructor/__proto__ 读取不触发原型链)。资源上限(对象与字符串两条输入路径统一执行):
- 查询表达式长度 ≤ 200 字符、解析深度 ≤ 20 层、数组索引必须是安全整数
- 字符串输入 ≤ 1,000,000 bytes(UTF-8);输入嵌套深度 ≤ 100
- 单次 wildcard 投影 ≤ 100,000 元素
- 只接受 JSON-compatible 值(null/boolean/有限 number/string/array/plain object;拒绝 undefined/BigInt/函数/Date/非有限数)
错误分类(JsonQueryError):MISSING_PROPERTY(投影内跳过)、TYPE_MISMATCH/INDEX_OUT_OF_BOUNDS/INVALID_QUERY(如实抛错),统一 json: 前缀。
成本模型(AUDIT-JSON-03):输入在每次查询前执行全量校验(类型/深度/字节/循环/枚举性)——这是有意的安全成本,查询小字段也会完整扫描输入;
timeoutMs无法中断同步校验。
架构
DSH Agent
│ ctx.tools.register()
▼
src/index.ts(Cordis 插件入口 + action 分发)
│
▼
src/query.ts
├── parseQuery() — 递归下降解析器(strict 语法 + 转义 + 上限)
├── executeQuery() — 执行器(错误分类 + 投影上限)
└── normalizeInput() — 双形态输入 + assertJsonCompatible 校验
工具声明
ctx.tools.register(defineTool({
name: 'json',
parameters: {
input: { type: 'json', required: true, description: 'JSON value or JSON string to query.' },
query: { type: 'string', required: true, description: 'Path expression, e.g. "data.items[0].name".' },
},
output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: JSON.stringify(v) }] },
execute: (args) => Promise.resolve(executeAction(args) as JsonValue),
timeoutMs: 1000,
}))
input 双形态:对象直传(模型直接生成参数,零转义)或字符串(bash/read 原文透传),normalizeInput 统一归一化与校验。
查询语法(JMESPath-inspired 子集)
| 表达式 | 示例 | 说明 |
|---|---|---|
| 点号访问 | foo.bar |
嵌套对象属性(标识符字符集 [A-Za-z0-9_$ + BMP 非 ASCII]) |
| 方括号索引 | items[0] |
数组索引(安全整数) |
| 方括号属性 | items['key'] / items["key"] |
含特殊字符的属性名 |
| 通配符投影 | items[*].name |
仅数组;提取元素属性 |
| 组合嵌套 | a.b[0].c.d |
以上全部自由组合 |
语义边界(有意不兼容标准 JMESPath,已锁定):
- 多级通配符
items[*].tags[*]返回嵌套数组([['a','b'],['c']]),不做标准投影扁平化 - 通配符仅作用于数组,不支持对象字段枚举;非对象元素按投影语义跳过;合法
null结果保留 - 引号属性支持
\\\'\"三种转义(任意引号包围形式下均可用);非法转义报错 - 投影内只跳过
MISSING_PROPERTY;类型/索引/内部错误如实抛出
不支持(低频场景,bash + node 兜底):过滤器 [?downloads > 1000]、管道 |、函数调用。
npm 0.1.0-rc.6 兼容(已验证)
本插件已迁移到 npm 0.1.0-rc.6 依赖线,并在 @deepseek-ai/dsh@0.1.0-rc.6 的隔离 consumer 中完成全链路验证:
- 类型/运行时:
@deepseek-ai/cordis@^4.0.1+@deepseek-ai/dsh-tools@>=0.0.1-rc.1 <0.2.0+@deepseek-ai/dsh-invariants@>=0.0.1-rc.1 <0.2.0(peer);不再依赖 unscopedcordis - 独立构建:
npm install(devDependencies 自包含 typescript/vitest/@types/node)→npm run typecheck→npm test→npm run build→npm pack - 消费验证:tarball 装入 0.1.0-rc.6 consumer →
dsh --profile compat --dump-config出现本插件 row → 工具真实注册与执行通过 - 启动方式:
npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web(lib 生产模式;勿install -g全局安装)
版本适配
- 适配 DSH 版本: DSH 0.1.0-rc.6(npm)
- bundle 声明:
package.json的dsh.bundle(patch 指向cordis.patch.yml)+exports导出 - patch 格式:
cordis.patch.yml使用- insert:列表(patch 是 id-targeted 语义,裸- id:条目会报entry not found) - files: 发布 tarball 含
lib/、src/、cordis.patch.yml
安装
插件源码仓库:https://github.com/omdsh-dev/dsh-tool-json(public)。
Profile Bundle(推荐)
将本插件作为独立 bundle 安装到 profile(DSH 0.1.0-rc.6,npm):
# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-json
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-json
包内 dsh.bundle.patch(指向 cordis.patch.yml)会在安装后自动把插件加入 profile 的 layer stack;插件的 cordis.patch.yml 以 - insert: 插入 tool-json 条目。
⚠️ web 与 headless 是不同 profile:web 安装不会自动覆盖 headless;
dsh run默认使用 headless profile。
npm pack tarball 安装
npm pack # 生成 dsh-tool-json-*.tgz
dsh plugin --profile web add ./dsh-tool-json-*.tgz
dsh plugin --profile headless add ./dsh-tool-json-*.tgz
验证安装
dsh --profile web --dump-config | grep tool-json
运行验证
dsh run "使用 json 工具查询 {"a":{"b":1}} 的 a.b"
手动安装与旧版本兼容
仅适用于不支持 Profile Bundle 的旧快照或插件开发调试环境:
- 放入 monorepo:
cp -r json ~/.dsh/source/master/packages/tools/json(开发调试) apps/cli/package.json加"@deepseek-ai/dsh-tool-json": "workspace:^";tsconfig.host.jsonreferences 加{ "path": "./packages/tools/json" }pnpm install && pnpm run build- 在 profile 用户层 patch 插入插件(
~/.dsh/profiles/<name>/cordis.patch.yml):
- insert:
- id: tool-json
name: '@deepseek-ai/dsh-tool-json'
- 验证:
dsh --profile <name> --dump-config | grep tool-json
注意:patch 是 id-targeted 语义——裸
- id:条目会报entry "xxx" not found,必须用- insert:列表包裹。
用法
json { input: <JSON>, query: "items[0].name" } → "hello"
json { input: <JSON>, query: "items[*].name" } → ["a", "b"](合法 null 保留)
json { input: <JSON>, query: "items['complex-key']" } → "ok"
已知限制
- 只读:不能修改 JSON 字段(原地修改用
str_replace_editor/write;v2 可考虑set模式) - 无过滤器表达式、无标准 JMESPath 投影扁平化(见语义边界)
- 对象形态 input 依赖 DSH 参数管线保证 lossless JSON
测试
pnpm test
54 个用例(功能、错误、攻击载荷、对象/字符串双形态输入、资源上限与转义边界)。完整清单见本地维护的设计文档。
许可
MIT
链接
同类插件
liustack/modlens★ 1199
为纯文本模型架起视觉桥梁:粘贴图片,输出结构化 JSON 证据(OCR、版面、语义)。
Anionex/dsh-vision-toolkit★ 308
让纯文本模型更好地做视觉任务:带意图的图片问答、长截图 OCR、UI 还原等。
zhaoolee/notes★ 138
将 DSH 对话导出为锤子便签风格 PNG,或在配置的账号工作区中新建和更新 Markdown 便签。
liustack/modsearch★ 85
纯文本 agent 的联网搜索桥:搜索网页与 X,返回结构化 JSON 证据(search/fetch/引用)。
Lum1104/dsh-browser★ 80
Chrome 侧边栏扩展,让 DSH 直接操控你的浏览器,无需视觉能力。
taxueseek/argo★ 69
专为 agent 打造的搜索工具:多语言,覆盖中文/英文/学术/代码/购物/金融/新闻/百科。