An encoding/decoding tool usually gets implemented many times over: one set of JavaScript for the web version, another for the desktop, and when AI calls in, the model is left to improvise. Every additional consumer means one more implementation whose behaviour can drift.
We do the opposite: the algorithm is written once, lives in a Rust kernel, and is compiled into different forms to fit different consumers.
The kernel is pure functions, with no IO
Every algorithm in newtool-core is a pure function — data in, data out, no file reads, no network requests. This constraint buys two things: the kernel can be compiled to wasm and run in the browser, and the attack surface is minimal.
01// 纯函数:无 IO,可编译到原生与 wasm02pub fn decode_jwt(token: &str) -> Result<JwtParts, Error> {03 let (h, p, s) = split(token)?;04 Ok(JwtParts {05 header: b64url_decode(h)?,06 payload: b64url_decode(p)?,07 signature: s.to_string(),08 })09}The manifest is the single source of truth
Which algorithms exist, what their parameters are, in which forms they take effect — this information lives in manifests/algorithms.toml, not scattered across code comments or documents. The manifest drives code generation, and it drives visibility too.
01[[algorithm]]02id = "jwt.decode"03name = "JWT 解码"04status = "rust" # 强制与 registry 同步05forms = ["app", "cli", "web-wasm", "web-server"]0607[[algorithm.params]]08name = "token"09type = "string"10required = trueAt build time, build.rs compares the manifest against the registry. If the manifest declares an algorithm that has no implementation in the code (or the reverse), the build fails outright. This kind of check belongs at build time rather than in code review because it keeps working forever.
Three consumers, one implementation
- AI: invoked through the skills package or an MCP endpoint, in three steps — list / describe / run
- Humans: a Tauri 2 desktop app, calling in through the tauri adapter of kernel-client
- Browsers: the kernel compiles to wasm, works offline, and data never leaves the browser
The desktop shell’s kernel-client has three adapters (tauri / http / wasm), all pointing at the same kernel interface. Switching adapters just switches the runtime environment; algorithm behaviour does not change.
What it costs
- Rust iterates more slowly than scripting languages, and the bar for writing a new algorithm is higher
- Keeping the manifest and the code in sync takes extra build machinery and discipline
- Certain platform features are unavailable under the wasm target, so algorithm implementations have to steer around them
Cross-platform behavioural drift is the kind of defect that is hard to trace once it bites and persists forever if you never trace it. Eliminating it before it happens with build-time constraints is far cheaper than reconciling afterwards.