Skip to content
dsh.fish
Bundle

dsh-chem

Deterministic chemistry math for DeepSeek Harness (dsh): formula parsing with molar mass (nested parens, hydrates, ionic charges), mass/mole/particle conversions, solution concentration (molarity, dilution, percent) and pH/pOH/buffer math — zero runtime dependencies

Source
TYEclipse
stars
1 stars
License
MIT
Updated
Updated yesterday

Readme

# dsh-chem

Deterministic chemistry math for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`) — **zero runtime dependencies**, pure arithmetic over IUPAC data.

> 中文简介:化学计量数学工具箱。四个零依赖确定性工具——化学式解析与摩尔质量(支持嵌套括号、结晶水、离子电荷)、质量/摩尔/粒子数换算、溶液浓度(摩尔浓度、稀释 C1V1=C2V2、百分比浓度)、pH/pOH 与缓冲溶液。专门替代 LLM 高频出错的化学心算。

## Why this plugin

Agents get chemistry arithmetic wrong in predictable ways:

- **Molar-mass sums** — miscounted subscripts, dropped hydrates (CuSO4·5H2O is 249.68 g/mol, not 159.61).
- **Element case sensitivity** — "Co" is cobalt (58.93), "CO" is carbon monoxide (28.01).
- **Dilution math** — C1V1 = C2V2 with a wrong or missing factor.
- **pH log/antilog arithmetic** — pH of 0.01 M HCl is 2, not 12.

These tools replace all of it with deterministic tables and formulas. No network, no state, no dependencies — install and call.

## Tools

### `formula_mass` — parse a formula and compute molar mass

Accepts nested parentheses, hydrate dots (`CuSO4·5H2O`, `*` also works), leading coefficients (`2H2O`) and ionic charges. Uses IUPAC standard atomic weights; elements without stable isotopes use the most-stable-isotope mass number (flagged with `usedMassNumber`).

```json
{ "formula": "H2SO4" }
```

```json
{
  "valid": true,
  "formula": "H2SO4",
  "molarMass": 98.072,
  "elements": [
    { "symbol": "H", "name": "Hydrogen", "count": 2, "atomicMass": 1.008, "massContribution": 2.016, "massFraction": 0.02056 },
    { "symbol": "O", "name": "Oxygen", "count": 4, "atomicMass": 15.999, "massContribution": 63.996, "massFraction": 0.65254 },
    { "symbol": "S", "name": "Sulfur", "count": 1, "atomicMass": 32.06, "massContribution": 32.06, "massFraction": 0.32690 }
  ],
  "usedMassNumber": false
}
```

**Charge disambiguation rule** (documented, deterministic): digits immediately before a trailing `+`/`-` belong to the *ionic charge* only when every element parsed so far is the same single element — `Fe3+` is Fe with 3+, `S2-` is S with 2-, `Ca2+` is Ca with 2+. Otherwise they are a subscript and the bare sign is a 1-unit charge — `NH4+` is N + H4 with `+`, `NO3-` is N + O3 with `-`. The explicit form `SO4^2-` is always the charge, and `O2^+` escapes the rule for subscript-before-charge. Single lowercase symbols are auto-corrected (`h2o` → H2O); multi-letter lowercase runs are rejected with a case-sensitivity hint.

### `mass_moles` — mass / amount / particle conversions

Six modes (`mass_to_moles`, `moles_to_mass`, `mass_to_particles`, `particles_to_mass`, `moles_to_particles`, `particles_to_moles`), molar mass from a formula or given directly, Avogadro constant 6.02214076e23.

```json
{ "mode": "mass_to_moles", "value": 98, "formula": "H2SO4" }
```

```json
{ "valid": true, "mode": "mass_to_moles", "molarMass": 98.072, "avogadro": 6.02214076e+23, "formula": "H2SO4", "moles": 0.9992658455012644 }
```

### `solution` — concentration math

Four operations:

- `molarity` — mass of solute + volume → mol/L: `{ "operation": "molarity", "massG": 58.44, "volumeMl": 250, "formula": "NaCl" }` → `molarity: 4`
- `prepare` — target molarity + volume → solute mass: `{ "operation": "prepare", "molarity": 0.1, "volumeMl": 500, "formula": "NaOH" }` → `massG: 1.99985`
- `dilute` — C1V1 = C2V2, give any three of `c1`/`v1`/`c2`/`v2` (M, mL) and the missing one is computed: `{ "operation": "dilute", "c1": 2, "c2": 0.5, "v2": 250 }` → `v1: 62.5`, `solved: "v1"`
- `percent` — `wv` (g per 100 mL), `vv` (mL per 100 mL) or `mass` percent: `{ "operation": "percent", "percentType": "wv", "soluteG": 5, "solutionMl": 200 }` → `percent: 2.5`

### `ph` — pH chemistry at 25 °C (Kw = 1e-14)

Five operations:

- `from_h` — `{ "operation": "from_h", "hConc": 0.001 }` → `pH: 3, pOH: 11, ohConc: 1e-11`
- `from_oh` — [OH-] → pH/pOH
- `from_ph` — pH → [H+]
- `from_poh` — pOH → [OH-]
- `buffer` — Henderson–Hasselbalch: `{ "operation": "buffer", "pKa": 4.76, "acidConc": 0.2, "baseConc": 0.1 }` → `pH: 4.4589700043360185, bufferRatio: 0.5`

Negative pH for >1 M acids is supported ([H+] = 2 → pH −0.301).

## Install

```bash
dsh plugin --profile <profile> add github:TYEclipse/dsh-chem
```

(Requires `pnpm` on PATH — `dsh plugin` forwards installs to it.)

## Verify

```bash
dsh plugin --profile <profile> list      # dsh-chem present
dsh --dump-config --profile <profile>    # == dsh-chem layer present
```

## Development

```bash
pnpm install
pnpm build     # tsc -> dist/ (committed; git installs do not build)
pnpm test      # vitest, 102 tests
pnpm lint      # oxlint src test
```

All numeric anchors are generated by the independent Python oracle `test/anchors-chem.py` (own periodic table + own tokenizer) and cross-validated against published textbook molar masses (H2O 18.015, H2SO4 98.08, NaCl 58.44, Ca(OH)2 74.09, CuSO4·5H2O 249.68, C6H12O6 180.16, KMnO4 158.03, NH3 17.03).

## License

MIT

Install

dsh plugin --profile web add github:TYEclipse/dsh-chem

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source