pi-hashline-edit-pro 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-hashline-edit-pro",
3
- "version": "2.6.0",
3
+ "version": "2.6.1",
4
4
  "type": "module",
5
5
  "description": "Hash-anchored read/replace/undo tools for pi-coding-agent. Every line gets a unique 3-char hash (A-Za-z0-9) that stays stable across edits; stale or ambiguous anchors are rejected, never fuzzy-matched. Undo persists across restarts.",
6
6
  "main": "index.ts",
@@ -5,5 +5,4 @@
5
5
  - `replace`: when copying a line from read output, remove its HASH│ prefix and keep the leading whitespace exactly as shown.
6
6
  - `replace`: replacement_lines is an array of strings, one element per line. Mirror the removed lines exactly, blank lines included: use `[]` to delete the range, `[""]` for a single blank line, `["a", ""]` for a line followed by a blank line, and `["", ""]` for two blank lines. Do not embed `\n` inside an element — each element is exactly one line.
7
7
  - `replace`: when auto-read shows the post-edit diff, its rows are the fresh anchors for the new file — `+HASH│` and ` HASH│` rows carry current hashes and unchanged lines keep their previous hashes, so you can anchor follow-up edits on the diff without re-reading.
8
- - `replace`: `[E_RANGE_STALE]` means a line inside the replaced range changed on disk after it was last shown (or was never shown). Nothing was modified; the error lists the current range as `HASH│content` rows, so retry with those anchors and no `read`.
9
8
  - `replace`: do not issue multiple replace calls on the same file in one message. Issue the next edit only after verifying the previous diff.
package/src/file-kind.ts CHANGED
@@ -119,7 +119,9 @@ export async function loadFileKindAndText(
119
119
  description: detectedMimeType,
120
120
  };
121
121
  }
122
-
122
+ if (detectedMimeType === undefined && sample.includes(0)) {
123
+ return { kind: "binary", description: "contains NUL bytes" };
124
+ }
123
125
 
124
126
  const decoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
125
127
  let hadUtf8DecodeErrors = false;
@@ -258,7 +258,7 @@ function mapStableHashes(
258
258
 
259
259
  const removedByContent = new Map<string, { hashes: string[]; pos: number }>();
260
260
  for (const entry of removedEntries) {
261
- const key = canon(oldLines[entry.index]!);
261
+ const key = oldLines[entry.index]!;
262
262
  let queue = removedByContent.get(key);
263
263
  if (!queue) {
264
264
  queue = { hashes: [], pos: 0 };
@@ -269,7 +269,7 @@ function mapStableHashes(
269
269
 
270
270
  for (let i = 0; i < newLines.length; i++) {
271
271
  if (newHashes[i]) continue;
272
- const queue = removedByContent.get(canon(newLines[i]!));
272
+ const queue = removedByContent.get(newLines[i]!);
273
273
  if (!queue || queue.pos >= queue.hashes.length) continue;
274
274
  newHashes[i] = queue.hashes[queue.pos]!;
275
275
  queue.pos += 1;
@@ -455,11 +455,6 @@ export function valEdit(
455
455
  }
456
456
  return { resolved: undefined, mismatches, boundaryDups };
457
457
  }
458
- if (startResolved.line > endResolved.line) {
459
- throw new Error(
460
- `[E_BAD_OP] Range start line ${startResolved.line} must be <= end line ${endResolved.line} (anchors ${edit.hash_bounds[0].hash} and ${edit.hash_bounds[1].hash}).`,
461
- );
462
- }
463
458
  const endLine = endResolved.line;
464
459
  const rangeLines = fileLines.slice(startResolved.line - 1, endLine);
465
460
  const canonLines = fileLines.map((line) => canon(line));