npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tian.zuo/pi-edit-safe

v0.1.1

Published

A stricter edit tool for the pi coding agent with full-span match verification, verbatim replacement, and an array-only edits schema.

Readme

pi-edit-safe

A drop-in replacement for the pi coding agent's built-in edit tool, with a stricter matcher that refuses to silently edit the wrong place — and a call shape that weaker models can actually use.

Exposes one call shape — {path, edits: [...]}, always an array, even for a single replacement — so the model has nothing to choose per call. Multi-edit applies in order (sequential), the contract models assume from multi-edit tools elsewhere, instead of pi's all-against-the-original-file semantic.

The looser shapes models emit anyway are still folded onto that form before validation, so off-contract calls are normalized rather than rejected — they are just not advertised.

Install: npm:@tian.zuo/pi-edit-safe · npm package @tian.zuo/pi-edit-safe · workspace packages/pi-edit-safe

Call shape

One shape, always an array:

{ "path": "src/a.ts", "edits": [
	{ "oldText": "...", "newText": "..." },
	{ "oldText": "...", "newText": "..." }
] }

Use a one-element edits array for a single replacement. path and edits are both required and edits has minItems: 1. Nothing else is advertised to the model.

Tolerated but not advertised

prepareArguments runs before schema validation (per pi's extension contract) and folds these onto the canonical form: file_path/filePath/filename for path; old_string/new_string, oldString/newString, old_str/new_str for the pair (per entry or top-level); top-level oldText/newText shorthand; edits as a JSON string; and edits as a single object.

This keeps off-contract calls working without widening the public schema. Exact duplicate entries are rejected loudly. When a later edit fails because an earlier edit in the same call rewrote its target, the error says exactly that.

Design stance

| Decision | typical fuzzy edit tools | pi-edit-safe | |---|---|---| | Partial-signal strategies (first/last-line anchor) | yes | none | | On ambiguity | fall through to next candidate | throw immediately | | Fuzzy candidate validation | per-candidate similarity threshold | full-span structural equality + exactly-one + occurs-once | | Overlapping exact matches | often missed | caught (overlap-aware counting) | | Unicode punctuation drift (smart quotes, em dash, NBSP) | varies | strict unicode strategy, span-only | | Untouched bytes | may be normalized whole-file | never touched (slice + verbatim splice) | | Line endings | whole-file normalize/restore | span-boundary only; mixed-ending files never flattened | | newText write | String.replace ($& hazard) | slice-join (literal) | | Multi-edit semantics | all edits vs the original file | sequential, in order | | Call shapes offered to the model | varies | exactly one (edits[]) |

Fuzzy matching only ever locates a span. The replacement is spliced in verbatim — it is never re-indented or rewritten.

Matching order

  1. Exact, never gated, counted overlap-aware (aa in aaa is ambiguous, not unique).
  2. If exact fails, hard gates: ≥5 non-space chars, no NUL byte, ≤1M chars, ≤50k lines.
  3. Increasingly tolerant full-span strategies: line-trimmed → unicode punctuation → collapsed whitespace → escape-normalized.
  4. More than one candidate for a strategy → throw. Never falls through from ambiguity to a looser matcher.
  5. Splice verbatim. Uniform LF/CRLF files adapt the replacement's newlines; mixed-ending files take it as-is.
  6. Apply all entries in memory, in order, then write once — a later failure leaves the file unchanged.

Result details

Returns pi's built-in EditToolDetails shape (diff, patch, firstChangedLine) alongside a edits[] array of per-edit provenance (matchedVia, startLine, endLine).

Because pi resolves renderer inheritance per slot (toolDefinition.renderCall ?? builtInToolDefinition.renderCall), this override deliberately defines neither renderCall nor renderResult, and so inherits pi's streaming diff preview and final diff rendering for free.

The diff is computed against the real bytes on both sides. pi's built-in diffs its LF-normalized view instead, which is why the two disagree on mixed-line-ending files (see bench case 11).

Disable

PI_EDIT_SAFE_DISABLE=1 pi   # falls back to the built-in edit

Tests and A/B bench

pnpm --filter @tian.zuo/pi-edit-safe test    # 45 unit tests (Node's built-in runner)
pnpm --filter @tian.zuo/pi-edit-safe run bench

The bench imports pi's actual shipped edit-diff.js functions and composes them exactly as dist/core/tools/edit.js does, then runs the same 12 (file, edits) cases through both pipelines and reports every divergence, including "canary" lines that must stay byte-identical.

These are deterministic corruption regressions. They are not a model-level eval — no cross-model pass@1 / token / retry benchmark exists for this tool yet.

Attribution

Fuzzy-strategy concepts adapted from opencode (MIT, via cline MIT and gemini-cli Apache-2.0); the unicode normalization table mirrors pi's own normalizer (MIT), applied span-only. Design philosophy reproduced independently. See NOTICES.md.