DeepSeek Harness Plugin

omdsh-dev/dsh-tool-calculator

Stars ★ 5 Category Tools & Capabilities Added 2026-08-13

Safe math expression evaluator, zero-dependency recursive-descent parser.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

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

GitHub-sourced plugins run build scripts on your machine at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).

README

中文

DSH Calculator tool plugin — a safe mathematical expression evaluator. Zero dependencies, zero processes, pure functions.

License

Motivation

Agents being unreliable at arithmetic is a common weakness of LLMs. DSH's built-in bash tool can call echo $((15 + 27 * 3)) to do calculations, but it has two problems:

  1. Every arithmetic operation spawns a bash process — especially expensive on Windows (process creation, shell loading, execution, output collection), with noticeable cumulative latency under high-frequency calls
  2. bash arithmetic syntax is limited — it doesn't support math functions such as sqrt, sin, cos, log, pow; in these scenarios the agent can only guess the answer or write a script

This plugin provides a zero-dependency, zero-process, pure-function calculator — a single function call returns the result in milliseconds, covering common elementary math functions.

Security Model

No eval, no new Function. It uses a hand-written recursive descent parser (lexer layer + parser layer), evaluating only whitelisted nodes:

  • The lexer layer only recognizes numeric literals, whitelisted identifiers, and operators; quotes, semicolons, backticks, {} [] fail directly with an error
  • Identifiers are looked up by name in the whitelist table (15 functions + 2 constants); anything not found throws Unknown identifier
  • Evaluation results must be finite numbers; NaN/Infinity (division by zero, square root of a negative number, etc.) are uniformly rejected

new Function + regex whitelisting is unsafeconstructor.constructor(...) can reach the Function constructor directly and execute arbitrary code, and process.exit(0) can kill the host process outright (both reproduced in actual testing). This implementation uses no code-evaluation shortcuts.

Architecture

┌──────────────────────────────┐
│         DSH Agent             │
│  tool call: calculator { ... }│
└──────────┬───────────────────┘
           │ ctx.tools.register()
┌──────────▼───────────────────┐
│     src/index.ts             │
│     Cordis 插件入口           │
└──────────┬───────────────────┘
           │
┌──────────▼───────────────────┐
│     src/evaluate.ts          │
│     tokenize() → parse()     │
│     递归下降解析器            │
└──────────────────────────────┘
  • src/index.ts: Cordis plugin entry (name/inject/apply), registers the calculator tool
  • src/evaluate.ts: evaluate(expression: unknown): number — the entry point independently validates the type (throws calculator: expression must be a string for non-strings), returns finite numbers, and throws on all invalid input

Tool Declaration

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
import { evaluate } from './evaluate.ts'

export const name = '@deepseek-ai/dsh-tool-calculator'
export const inject = ['tools']

export function apply(ctx: Context): void {
  ctx.tools.register(defineTool({
    name: 'calculator',
    description:
      'Evaluate a mathematical expression safely. ' +
      'Supports +, -, *, /, %, **, parentheses, and functions: ' +
      'abs, ceil, floor, round, max, min, sqrt, pow, log, log2, log10, exp, sin, cos, tan, PI, E.',
    parameters: {
      expression: {
        type: 'string',
        required: true,
        description: 'Mathematical expression, e.g. "15 + 27 * sqrt(9)"',
      },
    },
    output: {
      schema: { type: 'number' },
      render: (_args, value) => [{ type: 'text', text: String(value) }],
    },
    execute: async (args) => evaluate(args.expression),
    timeoutMs: 1000,
  }))
}

Supported Operations

Category Items
Arithmetic + - * / % ** (power, right-associative: 2 ** 3 ** 2 = 512)
Functions (single arg) abs ceil floor round sqrt log log2 log10 exp sin cos tan
Functions (multiple args) pow(x, y) max(a, b, ...) min(a, b, ...)
Constants PI E
Grouping ( ), unary plus/minus +5 -5

Precedence: ** (right-associative) > unary ± > * / % > + -.

npm 0.1.0-rc.6 Compatibility (Verified)

This plugin has been migrated to the npm 0.1.0-rc.6 dependency line and fully verified end-to-end in an isolated consumer of @deepseek-ai/dsh@0.1.0-rc.6:

  • Types/runtime: @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); no longer depends on unscoped cordis
  • Standalone build: npm install (devDependencies self-contained: typescript/vitest/@types/node) → npm run typechecknpm testnpm run buildnpm pack
  • Consumption verification: tarball loaded into a 0.1.0-rc.6 consumer → dsh --profile compat --dump-config shows this plugin's row → the tool genuinely registers and executes
  • Launch method: npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web (lib production mode; don't install -g globally)

Version Adaptation

  • DSH adapted: DSH 0.1.0-rc.6 (npm) (migration: profile/bundle plugin system)
  • bundle declaration: dsh.bundle in package.json (patch points to cordis.patch.yml) + exports export
  • patch format: cordis.patch.yml uses the - insert: list (the DSH 0.1.0-rc.6 (npm) patch is id-targeted semantics; a bare - id: entry reports entry not found)
  • files: the published tarball contains lib/, src/, cordis.patch.yml

Installation

Profile Bundle (Recommended)

As of DSH 0.1.0-rc.6 (npm), this plugin can be installed into any profile as a standalone bundle in one step (repositories live at https://github.com/omdsh-dev, public):

# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-calculator
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-calculator

You can also pack a tarball with npm pack first and install that:

git clone https://github.com/omdsh-dev/dsh-tool-calculator
cd dsh-tool-calculator
npm install && npm pack
dsh plugin --profile web add ./deepseek-ai-dsh-tool-calculator-*.tgz
dsh plugin --profile headless add ./deepseek-ai-dsh-tool-calculator-*.tgz

The in-package dsh.bundle.patch (pointing to cordis.patch.yml) automatically adds the plugin to the profile's layer stack after installation; the plugin's cordis.patch.yml inserts the tool-calculator entry via - insert:. The plugin's missing peer dependencies (@deepseek-ai/cordis, @deepseek-ai/dsh-tools, @deepseek-ai/dsh-invariants) are provided by the profile's healed profiles/node_modules fallback installation.

⚠️ web and headless are different profiles: installing for web doesn't automatically cover headless; dsh run uses the headless profile by default. Use forward slashes for Windows paths (C:/...).

Verify Installation

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

Runtime Verification

dsh run "使用 calculator 工具计算 1+2*3"

Manual Installation (Source Contribution / Legacy Snapshot Scenarios)

For source contribution (developing/debugging this plugin in the monorepo) or for scenarios still using old snapshots:

  1. Place it in the monorepo: cp -r calculator ~/.dsh/source/master/packages/tools/calculator (dev debugging)
  2. Add "@deepseek-ai/dsh-tool-calculator": "workspace:^" to apps/cli/package.json; add { "path": "./packages/tools/calculator" } to the tsconfig.host.json references
  3. pnpm install && pnpm run build
  4. Insert the plugin in the profile user-layer patch (~/.dsh/profiles/<name>/cordis.patch.yml):
- insert:
    - id: tool-calculator
      name: '@deepseek-ai/dsh-tool-calculator'
  1. Verify: dsh --profile <name> --dump-config | grep tool-calculator

DSH 0.1.0-rc.6 (npm) note: the patch is id-targeted semantics — a bare - id: entry reports entry "xxx" not found; it must be wrapped in a - insert: list.

Usage

After installation, the agent automatically gets the calculator tool:

calculator { expression: "15 + 27 * sqrt(9)" }  →  96

The tool name satisfies DeepSeek's function-name constraints (≤64 characters, [A-Za-z0-9_-]). After registration it automatically enters the Code Mode SDK (await tools.calculator(...)), and the canonical return value is a number.

Known Limitations

  1. Distribution chain: @deepseek-ai/dsh-tools is now published as a private npm package with DSH 0.1.0-rc.6 (npm); the plugin installs directly via dsh plugin add github:omdsh-dev/... or the tarball, with no need to place it in the monorepo for workspace resolution
  2. Trigonometric functions use radians: consistent with Math.sin/Math.cos; write sin(30 * PI / 180) when you need degrees
  3. No big integers: JS number is an IEEE 754 double; the safe integer range is ±9e15, beyond which precision is lost
  4. No scientific notation: 1e5 is rejected by the lexer layer

Testing

pnpm test

Includes functional test cases and attack-payload cases (constructor.constructor chain, process.exit(0), globalThis, quote injection, semicolon statements, etc.). The complete case list is in the locally maintained design document.

License

MIT

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →