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
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-chem from the hub
- 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.