pi-startup-redraw-fix 0.1.11 → 0.1.13
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/CHANGELOG.md +13 -0
- package/package.json +64 -64
- package/src/constants.ts +1 -2
- package/src/index.ts +5 -0
- package/src/normalize-clear-sequence.ts +1 -9
- package/src/terminal-clear-patch.ts +44 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.1.13] - 2026-06-16
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Buffered trailing broken clear-sequence prefixes across multiple `write` calls so split escape sequences that arrive in separate chunks are correctly normalized instead of being silently discarded.
|
|
9
|
+
|
|
10
|
+
## [0.1.12] - 2026-06-01
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Consolidated clear-sequence constants and normalization into the terminal clear patch while preserving synchronous startup patching.
|
|
14
|
+
- Widened peer dependency ranges to `^0.74.0 || ^0.75.0 || ^0.77.0 || ^0.78.0`.
|
|
15
|
+
|
|
3
16
|
## [0.1.11] - 2026-05-26
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-startup-redraw-fix",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Pi extension that patches terminal full-clear ordering to avoid startup redraw glitches.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./index.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": "./index.ts"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.ts",
|
|
12
|
-
"src",
|
|
13
|
-
"asset",
|
|
14
|
-
"config/config.example.json",
|
|
15
|
-
"README.md",
|
|
16
|
-
"CHANGELOG.md",
|
|
17
|
-
"LICENSE"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "npx --yes -p typescript@5.7.3 tsc -p tsconfig.json --noCheck",
|
|
21
|
-
"lint": "npm run build",
|
|
22
|
-
"test": "npx --yes tsx --test normalize-clear-sequence.test.mjs",
|
|
23
|
-
"check": "npm run lint && npm run test"
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"pi-package",
|
|
27
|
-
"pi",
|
|
28
|
-
"pi-extension",
|
|
29
|
-
"pi-coding-agent",
|
|
30
|
-
"pi-tui",
|
|
31
|
-
"coding-agent",
|
|
32
|
-
"terminal",
|
|
33
|
-
"terminal-emulator",
|
|
34
|
-
"startup",
|
|
35
|
-
"startup-fix",
|
|
36
|
-
"redraw",
|
|
37
|
-
"bugfix"
|
|
38
|
-
],
|
|
39
|
-
"author": "MasuRii",
|
|
40
|
-
"license": "MIT",
|
|
41
|
-
"repository": {
|
|
42
|
-
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/MasuRii/pi-startup-redraw-fix.git"
|
|
44
|
-
},
|
|
45
|
-
"bugs": {
|
|
46
|
-
"url": "https://github.com/MasuRii/pi-startup-redraw-fix/issues"
|
|
47
|
-
},
|
|
48
|
-
"homepage": "https://github.com/MasuRii/pi-startup-redraw-fix#readme",
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=20"
|
|
51
|
-
},
|
|
52
|
-
"publishConfig": {
|
|
53
|
-
"access": "public"
|
|
54
|
-
},
|
|
55
|
-
"pi": {
|
|
56
|
-
"extensions": [
|
|
57
|
-
"./index.ts"
|
|
58
|
-
]
|
|
59
|
-
},
|
|
60
|
-
"peerDependencies": {
|
|
61
|
-
"@earendil-works/pi-coding-agent": "^0.74.0 || ^0.75.0",
|
|
62
|
-
"@earendil-works/pi-tui": "^0.74.0 || ^0.75.0"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-startup-redraw-fix",
|
|
3
|
+
"version": "0.1.13",
|
|
4
|
+
"description": "Pi extension that patches terminal full-clear ordering to avoid startup redraw glitches.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.ts",
|
|
12
|
+
"src",
|
|
13
|
+
"asset",
|
|
14
|
+
"config/config.example.json",
|
|
15
|
+
"README.md",
|
|
16
|
+
"CHANGELOG.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "npx --yes -p typescript@5.7.3 tsc -p tsconfig.json --noCheck",
|
|
21
|
+
"lint": "npm run build",
|
|
22
|
+
"test": "npx --yes tsx --test normalize-clear-sequence.test.mjs",
|
|
23
|
+
"check": "npm run lint && npm run test"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"pi-package",
|
|
27
|
+
"pi",
|
|
28
|
+
"pi-extension",
|
|
29
|
+
"pi-coding-agent",
|
|
30
|
+
"pi-tui",
|
|
31
|
+
"coding-agent",
|
|
32
|
+
"terminal",
|
|
33
|
+
"terminal-emulator",
|
|
34
|
+
"startup",
|
|
35
|
+
"startup-fix",
|
|
36
|
+
"redraw",
|
|
37
|
+
"bugfix"
|
|
38
|
+
],
|
|
39
|
+
"author": "MasuRii",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/MasuRii/pi-startup-redraw-fix.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/MasuRii/pi-startup-redraw-fix/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/MasuRii/pi-startup-redraw-fix#readme",
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=20"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"pi": {
|
|
56
|
+
"extensions": [
|
|
57
|
+
"./index.ts"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@earendil-works/pi-coding-agent": "^0.74.0 || ^0.75.0 || ^0.77.0 || ^0.78.0 || ^0.79.0",
|
|
62
|
+
"@earendil-works/pi-tui": "^0.74.0 || ^0.75.0 || ^0.77.0 || ^0.78.0 || ^0.79.0"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export const FIXED_FULL_CLEAR_SEQUENCE = "\x1b[H\x1b[2J\x1b[3J";
|
|
1
|
+
export { BROKEN_FULL_CLEAR_SEQUENCE, FIXED_FULL_CLEAR_SEQUENCE } from "./terminal-clear-patch.js";
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,11 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import { applyTerminalClearSequencePatch } from "./terminal-clear-patch.js";
|
|
4
4
|
|
|
5
5
|
export default function startupRedrawFixExtension(pi: ExtensionAPI): void {
|
|
6
|
+
// The terminal clear-sequence patch must be installed before the first
|
|
7
|
+
// full-clear write at startup, so it is applied synchronously at registration
|
|
8
|
+
// rather than deferred. The local import graph is tiny (a few dozen lines) and
|
|
9
|
+
// the only package dependency, pi-tui, is already loaded by Pi core, so there
|
|
10
|
+
// is no meaningful startup transpile cost to defer here.
|
|
6
11
|
const patchResult = applyTerminalClearSequencePatch();
|
|
7
12
|
|
|
8
13
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export function normalizeTerminalClearSequence(data: string): string {
|
|
4
|
-
if (!data.includes(BROKEN_FULL_CLEAR_SEQUENCE)) {
|
|
5
|
-
return data;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return data.split(BROKEN_FULL_CLEAR_SEQUENCE).join(FIXED_FULL_CLEAR_SEQUENCE);
|
|
9
|
-
}
|
|
1
|
+
export { normalizeTerminalClearSequence } from "./terminal-clear-patch.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ProcessTerminal } from "@earendil-works/pi-tui";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export const BROKEN_FULL_CLEAR_SEQUENCE = "\x1b[3J\x1b[2J\x1b[H";
|
|
4
|
+
export const FIXED_FULL_CLEAR_SEQUENCE = "\x1b[H\x1b[2J\x1b[3J";
|
|
4
5
|
|
|
5
6
|
const PATCH_FLAG_KEY = "__piStartupRedrawFixPatched__" as const;
|
|
6
7
|
|
|
@@ -14,6 +15,31 @@ export interface PatchResult {
|
|
|
14
15
|
error?: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
export function normalizeTerminalClearSequence(data: string): string {
|
|
19
|
+
if (!data.includes(BROKEN_FULL_CLEAR_SEQUENCE)) {
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return data.split(BROKEN_FULL_CLEAR_SEQUENCE).join(FIXED_FULL_CLEAR_SEQUENCE);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function splitTrailingBrokenClearPrefix(data: string): { ready: string; pending: string } {
|
|
27
|
+
const maxPrefixLength = BROKEN_FULL_CLEAR_SEQUENCE.length - 1;
|
|
28
|
+
const maxCandidateLength = Math.min(maxPrefixLength, data.length);
|
|
29
|
+
|
|
30
|
+
for (let length = maxCandidateLength; length > 0; length -= 1) {
|
|
31
|
+
const suffix = data.slice(-length);
|
|
32
|
+
if (BROKEN_FULL_CLEAR_SEQUENCE.startsWith(suffix)) {
|
|
33
|
+
return {
|
|
34
|
+
ready: data.slice(0, -length),
|
|
35
|
+
pending: suffix,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { ready: data, pending: "" };
|
|
41
|
+
}
|
|
42
|
+
|
|
17
43
|
export function applyTerminalClearSequencePatch(): PatchResult {
|
|
18
44
|
const prototype = ProcessTerminal.prototype as ProcessTerminalPrototype;
|
|
19
45
|
|
|
@@ -30,12 +56,25 @@ export function applyTerminalClearSequencePatch(): PatchResult {
|
|
|
30
56
|
};
|
|
31
57
|
}
|
|
32
58
|
|
|
59
|
+
let pendingClearPrefix = "";
|
|
60
|
+
|
|
33
61
|
prototype.write = function patchedProcessTerminalWrite(data: string): void {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
62
|
+
if (typeof data !== "string") {
|
|
63
|
+
if (pendingClearPrefix.length > 0) {
|
|
64
|
+
originalWrite.call(this, pendingClearPrefix);
|
|
65
|
+
pendingClearPrefix = "";
|
|
66
|
+
}
|
|
67
|
+
originalWrite.call(this, data);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const combined = `${pendingClearPrefix}${data}`;
|
|
72
|
+
const { ready, pending } = splitTrailingBrokenClearPrefix(combined);
|
|
73
|
+
pendingClearPrefix = pending;
|
|
37
74
|
|
|
38
|
-
|
|
75
|
+
if (ready.length > 0) {
|
|
76
|
+
originalWrite.call(this, normalizeTerminalClearSequence(ready));
|
|
77
|
+
}
|
|
39
78
|
};
|
|
40
79
|
|
|
41
80
|
prototype[PATCH_FLAG_KEY] = true;
|