pi-double-esc 1.0.15 → 1.0.17
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 +7 -0
- package/double-esc.ts +36 -5
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -102,6 +102,13 @@ npm run lint:dead # check for unused exports
|
|
|
102
102
|
|
|
103
103
|
MIT
|
|
104
104
|
|
|
105
|
+
## Pi 1.0 compatibility (1.0.16)
|
|
106
|
+
|
|
107
|
+
Tested against Pi **1.1.0** with exact SDK development pins and wildcard host peers.
|
|
108
|
+
Editor composition, autocomplete Escape, timer cleanup and shutdown restoration remain intact.
|
|
109
|
+
|
|
110
|
+
Run `bun run test:host` for the offline real-host regression. Set `PI1_HOST_PACKAGE` to an installed Pi package directory and `PI1_HOST_ENTRY=bundle` to test its bundled CLI runtime.
|
|
111
|
+
|
|
105
112
|
## Pi 0.99 compatibility (1.0.15)
|
|
106
113
|
|
|
107
114
|
Preserves single-Escape autocomplete dismissal, restores editor methods/factories and clears debounce timers on shutdown. Non-TUI sessions are untouched; cached render output is not mutated.
|
package/double-esc.ts
CHANGED
|
@@ -134,24 +134,53 @@ function decorateDoubleEscapeEditor(
|
|
|
134
134
|
const DECORATED_FACTORY = Symbol("pi-double-esc.decoratedFactory");
|
|
135
135
|
|
|
136
136
|
type EditorFactory = NonNullable<ReturnType<ExtensionContext["ui"]["getEditorComponent"]>>;
|
|
137
|
-
|
|
137
|
+
// Shared with cooperating editor decorators: inactive factories are skipped
|
|
138
|
+
// when an outer owner later unwinds, regardless of shutdown order.
|
|
139
|
+
const EDITOR_FACTORY_PATCH = Symbol.for("pi.editor-factory.patch.v1");
|
|
140
|
+
type DecoratedEditorFactory = EditorFactory & {
|
|
141
|
+
[DECORATED_FACTORY]?: true;
|
|
142
|
+
[EDITOR_FACTORY_PATCH]?: { active: boolean; original?: EditorFactory };
|
|
143
|
+
};
|
|
144
|
+
function unwrapEditorFactory(factory: EditorFactory | undefined): EditorFactory | undefined {
|
|
145
|
+
while (factory) {
|
|
146
|
+
const state = (factory as DecoratedEditorFactory)[EDITOR_FACTORY_PATCH];
|
|
147
|
+
if (!state || state.active) return factory;
|
|
148
|
+
factory = state.original;
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function hasDoubleEscape(factory: EditorFactory | undefined): boolean {
|
|
154
|
+
while (factory) {
|
|
155
|
+
const wrapped = factory as DecoratedEditorFactory;
|
|
156
|
+
const state = wrapped[EDITOR_FACTORY_PATCH];
|
|
157
|
+
if (state?.active !== false && wrapped[DECORATED_FACTORY]) return true;
|
|
158
|
+
factory = state?.original;
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
138
162
|
|
|
139
163
|
export default function (pi: ExtensionAPI) {
|
|
140
164
|
const cleanups = new Set<() => void>();
|
|
141
165
|
let installed: DecoratedEditorFactory | undefined;
|
|
142
166
|
let previous: EditorFactory | undefined;
|
|
167
|
+
const factoryStates: { active: boolean; original?: EditorFactory }[] = [];
|
|
143
168
|
pi.on("session_start", (_event, ctx) => {
|
|
144
169
|
if (ctx.mode !== "tui") return;
|
|
145
|
-
const previousEditorFactory = ctx.ui.getEditorComponent() as DecoratedEditorFactory | undefined;
|
|
146
|
-
if (previousEditorFactory
|
|
170
|
+
const previousEditorFactory = unwrapEditorFactory(ctx.ui.getEditorComponent()) as DecoratedEditorFactory | undefined;
|
|
171
|
+
if (hasDoubleEscape(previousEditorFactory)) return;
|
|
147
172
|
|
|
173
|
+
const state = { active: true, original: previousEditorFactory };
|
|
148
174
|
const editorFactory: DecoratedEditorFactory = (tui, editorTheme, keybindings) => {
|
|
149
175
|
const editor =
|
|
150
|
-
previousEditorFactory?.(tui, editorTheme, keybindings) ??
|
|
176
|
+
unwrapEditorFactory(previousEditorFactory)?.(tui, editorTheme, keybindings) ??
|
|
151
177
|
new CustomEditor(tui, editorTheme, keybindings);
|
|
178
|
+
if (!state.active) return editor;
|
|
152
179
|
return decorateDoubleEscapeEditor(editor, tui, ctx.ui.theme, () => ctx.isIdle(), (cleanup) => cleanups.add(cleanup));
|
|
153
180
|
};
|
|
154
181
|
editorFactory[DECORATED_FACTORY] = true;
|
|
182
|
+
editorFactory[EDITOR_FACTORY_PATCH] = state;
|
|
183
|
+
factoryStates.push(state);
|
|
155
184
|
|
|
156
185
|
previous = previousEditorFactory;
|
|
157
186
|
installed = editorFactory;
|
|
@@ -160,7 +189,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
160
189
|
pi.on("session_shutdown", (_event, ctx) => {
|
|
161
190
|
for (const cleanup of cleanups) cleanup();
|
|
162
191
|
cleanups.clear();
|
|
163
|
-
|
|
192
|
+
for (const state of factoryStates) state.active = false;
|
|
193
|
+
factoryStates.length = 0;
|
|
194
|
+
if (installed && ctx.ui.getEditorComponent() === installed) ctx.ui.setEditorComponent(unwrapEditorFactory(previous));
|
|
164
195
|
installed = undefined;
|
|
165
196
|
previous = undefined;
|
|
166
197
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-double-esc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "Prevent accidental Escape from aborting the LLM — requires double-press to interrupt while streaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Tom X Nguyen",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"README.md"
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
|
+
"test:host": "node scripts/pi1-host.mjs",
|
|
33
34
|
"test": "vitest run",
|
|
34
35
|
"test:watch": "vitest",
|
|
35
36
|
"test:coverage": "vitest run --coverage",
|
|
@@ -37,8 +38,8 @@
|
|
|
37
38
|
"lint:dead": "knip --no-gitignore"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@earendil-works/pi-coding-agent": "
|
|
41
|
-
"@earendil-works/pi-tui": "
|
|
41
|
+
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
42
|
+
"@earendil-works/pi-tui": "1.1.0",
|
|
42
43
|
"@types/node": "25.9.1",
|
|
43
44
|
"@vitest/coverage-v8": "4.1.7",
|
|
44
45
|
"knip": "6.14.1",
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
]
|
|
52
53
|
},
|
|
53
54
|
"overrides": {
|
|
54
|
-
"brace-expansion": "5.0.
|
|
55
|
+
"brace-expansion": "5.0.12"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
58
|
"@earendil-works/pi-coding-agent": "*",
|