Introduction

In DSH plugin development, Agents often need to read JSON from API return values, configuration files, or tool outputs. If using simple string search, it is easy to mix up keys, values, and keys with the same name in nested objects; if a full JSON query engine is introduced, the cost may not be suitable for lightweight tools.

omdsh-dev/dsh-tool-json is a DSH tool plugin: it registers a tool named json, accepts JSON value or JSON string as input, and retrieves fields using a JMESPath-inspired path query (custom subset). Below is an introduction to its positioning, capabilities, installation methods, and precautions.

What is this

This is a read-only JSON query plugin.

  • Repository: omdsh-dev/dsh-tool-json
  • Package name: @deepseek-ai/dsh-tool-json
  • Maintainer: omdsh-dev
  • License: MIT
  • Current package.json version: 0.0.1
  • Compatible DSH: 0.1.2-alpha.2 (npm)
  • Installation method: Supports Profile Bundle, as well as npm pack tarball installation

It provides the DSH tool json. When called, pass input and query: input is the JSON value or JSON string to query, and query is the path expression. The plugin executes the query and returns the corresponding field value.

Core Features

Provide json tool

The parameters in the tool declaration include:

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".'
}

input supports two forms: passing the object directly, or passing a JSON string. The plugin uses normalizeInput for unified normalization and validation. The timeout specified in the tool declaration is:

timeoutMs: 1000

Query subset

This plugin supports a subset of JMESPath-inspired path queries and does not implement the full JMESPath.

Common expressions include:

Expression Example Description
Dot notation access a.b Access nested object properties
Bracket array index items[0] Access array elements
Bracket quoted property items['complex-key'] Access property names containing special characters
Array wildcard projection items[*].name Extract specified properties from array elements
Combined nesting a.b[0].c.d Free combination of the above forms

It only acts on query retrieval and does not modify JSON fields.

Error model

Query errors are uniformly categorized as JsonQueryError with the json: prefix.

Verified error types include:

  • MISSING_PROPERTY
  • TYPE_MISMATCH
  • INDEX_OUT_OF_BOUNDS
  • INVALID_QUERY

Among them, MISSING_PROPERTY is skipped within projections; TYPE_MISMATCH, INDEX_OUT_OF_BOUNDS, and INVALID_QUERY are thrown as is.

Query Syntax

Below are several typical path expressions.

Single value query

json { input: <JSON>, query: "items[0].name" }

Example returns:

"hello"

Array projection

json { input: <JSON>, query: "items[*].name" }

Example returns:

["a", "b"]

Valid null values are preserved.

Special key query

json { input: <JSON>, query: "items['complex-key']" }

Example returns:

"ok"

Multi-level wildcard

Multi-level wildcards like items[*].tags[*] return nested arrays and do not perform standard JMESPath projection flattening.

For example, standard JMESPath might expect a flattened array, but this plugin returns a nested structure.

Semantic Boundaries

This plugin is intentionally incompatible with full JMESPath.

Verified limitations include:

  • Wildcards only apply to arrays
  • Object field enumeration is not supported
  • Multi-level wildcards return nested arrays
  • Standard JMESPath projection flattening is not performed
  • Filter expressions, such as [?downloads > 1000], are not supported
  • The pipe | is not supported
  • Function calls are not supported

If your requirement is to modify JSON fields, this plugin is not suitable because it is read-only and cannot modify JSON fields.

Security and Resource Limits

The plugin uses a hand-written recursive descent parser and does not use eval or new Function. It uses Object.hasOwn for object property access to avoid triggering the prototype chain.

The verified resource limits are as follows:

  • Query expression length: ≤ 200 characters
  • Parse depth: ≤ 20 layers
  • String input: ≤ 1,000,000 bytes
  • Input nesting depth: ≤ 100
  • Single wildcard projection: ≤ 100,000 elements

Input only accepts JSON-compatible values:

  • null
  • boolean
  • Finite number
  • string
  • array
  • plain object

Note: Input is fully validated before every query. Since validation is a synchronous process, timeoutMs cannot interrupt synchronous validation.

Installation and Usage

Confirm dependencies

This plugin is compatible with DSH 0.1.2-alpha.2 (npm).

The engines requirement in package.json:

"node": "^22.19.0 || >=24.0.0"

The peerDependencies requirements:

{
  "@deepseek-ai/cordis": "^4.0.1",
  "@deepseek-ai/dsh-invariants": ">=0.0.1-rc.1 <0.2.0",
  "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1 <0.2.0"
}

Installation by profile

web and headless are different profiles. web installation does not automatically overwrite headless; dsh run defaults to the headless profile.

If you want to install to the web profile:

dsh plugin --profile web add github:omdsh-dev/dsh-tool-json

If you want to install to the headless profile:

dsh plugin --profile headless add github:omdsh-dev/dsh-tool-json

Which profile to choose depends on whether you will use web or dsh run later.

Profile Bundle mechanism

The dsh.bundle.patch in the package’s package.json points to:

./cordis.patch.yml

After installation, the plugin enters the profile’s layer stack. The plugin’s cordis.patch.yml uses a - insert: list to insert entries.

If using a bare - id: entry, it will report entry not found. The correct way is to wrap it with a - insert: list.

Verify installation

You can check if the plugin entry appears in the configuration:

dsh --profile web --dump-config | grep tool-json

Installation via npm pack tarball

You can also install by packing locally:

npm pack
dsh plugin --profile web add ./dsh-tool-json-*.tgz
dsh plugin --profile headless add ./dsh-tool-json-*.tgz

The published tarball includes:

lib/
src/
cordis.patch.yml

Typical Usage

Below are the query examples given in the plugin documentation.

Query a single field

json { input: <JSON>, query: "items[0].name" }

Returns:

"hello"

Query multiple fields in an array

json { input: <JSON>, query: "items[*].name" }

Returns:

["a", "b"]

Valid null values are preserved.

Query with special character keys

json { input: <JSON>, query: "items['complex-key']" }

Returns:

"ok"

Call via dsh run

You can require DSH to use the json tool to complete the query:

dsh run "使用 json 工具查询 {"a":{"b":1}} 的 a.b"

Applicable Scenarios and Notes

Suitable scenarios

  • Retrieving values from JSON along clear paths
  • Querying fixed structure fields in arrays
  • Querying property names containing special characters
  • Using this plugin in DSH Agents to replace temporary scripts for read-only JSON value retrieval

Unsuitable scenarios

  • Need to modify JSON fields
  • Need filter expressions
  • Need the pipe |
  • Need function calls
  • Need object field enumeration
  • Need the projection flattening behavior of standard JMESPath

Security notes

The plugin executes queries under the permissions of the current dsh process. Before installation, you should check the source code and license to ensure its behavior meets your security requirements.

This plugin is MIT licensed, and the public repository address is:

https://github.com/omdsh-dev/dsh-tool-json

Conclusion

omdsh-dev/dsh-tool-json solves a specific problem: retrieving values from JSON using structured paths in DSH. It does not replace full JMESPath, but rather provides a zero-dependency, read-only query subset with clear resource limits.

If you need an Agent to stably read JSON fields in the web or headless profile, you can first install it according to the target profile, then use dsh --profile <profile> --dump-config to verify if the plugin has entered the configuration.

Source code address:

https://github.com/omdsh-dev/dsh-tool-json