pi-hashline-edit-pro 2.2.0 → 2.2.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/README.md CHANGED
@@ -86,7 +86,7 @@ One edit per call, with `hash_bounds` and `new_content` at the top level:
86
86
  | Field | Description |
87
87
  | --- | --- |
88
88
  | `hash_bounds` | Pair of 3-char hashes from `read` output marking the first and last line of the range to replace (inclusive). |
89
- | `new_content` | Replacement content as a single string with `\n` line separators; a trailing newline is the last line's ending, not an extra empty line. Use `""` to delete the range. |
89
+ | `new_content` | Replacement content as a single string with `\n` line separators; every `\n` separates lines, so a trailing `\n` adds a final empty line — mirror the replaced range's lines exactly, blank lines included (a replacement that is only blank lines is written as one `\n` per blank line). Use `""` to delete the range. |
90
90
 
91
91
  Notes:
92
92
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "pi-hashline-edit-pro",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "type": "module",
5
- "description": "Strict hashline read/replace tool for pi-coding-agent with hash-anchored edits (3-char, 62-symbol, perfect hashing)",
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",
7
7
  "repository": {
8
8
  "type": "git",
@@ -16,7 +16,14 @@
16
16
  "extension",
17
17
  "hashline",
18
18
  "hash-anchored",
19
- "strict"
19
+ "hash",
20
+ "anchors",
21
+ "read",
22
+ "replace",
23
+ "edit",
24
+ "undo",
25
+ "file-editing",
26
+ "stable"
20
27
  ],
21
28
  "license": "MIT",
22
29
  "files": [
@@ -2,5 +2,5 @@
2
2
  - `replace`: minimize the replaced range — anchor only the lines that actually change, so few unchanged lines must be reproduced byte-exact.
3
3
  - `replace`: to replace a single line, repeat its hash in both positions of hash_bounds: ["<HASH>", "<HASH>"] — never extend the range to neighboring lines for a one-line edit.
4
4
  - `replace`: when copying a line from read output, remove its HASH│ prefix and keep the leading whitespace exactly as shown.
5
- - `replace`: to add a blank line, end new_content with an explicit empty line (e.g. ending with \n\n).
5
+ - `replace`: every `\n` in new_content separates lines, so a trailing `\n` adds a final empty line. Mirror the replaced range's lines exactly: a range that ends on a blank line must end new_content with `\n` (e.g. `"code\n"`), and a replacement whose last line is not blank must not end with `\n`. To add a blank line after a line, end new_content with an explicit empty line after it (e.g. `"X\n"` adds a blank after X). A replacement that is only blank lines is written as one `\n` per blank line (e.g. `"\n"` is a single blank line).
6
6
  - `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. `-HASH│` rows show removed lines with their old hashes; those hashes are stale after the edit.
@@ -45,7 +45,6 @@ export function parseText(edit: string): string[] {
45
45
  }
46
46
  const normalized = edit.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
47
47
  if (normalized === "") return [];
48
- const lines = normalized.split("\n");
49
- if (normalized.endsWith("\n")) lines.pop();
50
- return lines;
48
+ if (/^\n+$/.test(normalized)) return new Array(normalized.length).fill("");
49
+ return normalized.split("\n");
51
50
  }
package/src/replace.ts CHANGED
@@ -47,7 +47,7 @@ import { loadHashStore, type HashStore } from "./hash-store";
47
47
 
48
48
  const newContentSchema = Type.String({
49
49
  description:
50
- "Replacement content as a single string with \\n line separators; a trailing newline is the last line's ending, not an extra empty line. Use \"\" to delete the range."
50
+ "Replacement content as a single string with \\n line separators; every \\n separates lines, so a trailing \\n adds a final empty line. Mirror the replaced range's lines exactly, blank lines included. A replacement that is only blank lines is written as one \\n per blank line. Use \"\" to delete the range."
51
51
  });
52
52
 
53
53
  const hashBoundsSchema = Type.Array(