@gonrocca/zero-pi 0.1.32 → 0.1.33
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/extensions/zero-banner.ts +48 -8
- package/package.json +1 -1
|
@@ -134,18 +134,58 @@ export function bannerBlock(width: number): string[] {
|
|
|
134
134
|
return [ornament(width), "", ...renderLogo(width), "", center(tag, width), ornament(width)];
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
/** The slice of pi's UI surface this extension uses. */
|
|
138
|
+
interface PiUI {
|
|
139
|
+
setWidget(id: string, lines: string[]): void;
|
|
140
|
+
}
|
|
141
|
+
interface PiSessionContext {
|
|
142
|
+
ui?: PiUI;
|
|
143
|
+
}
|
|
144
|
+
interface PiAPI {
|
|
145
|
+
on(event: string, handler: (event: unknown, ctx: PiSessionContext) => void): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Stable widget id — re-installing with the same id replaces the previous lines. */
|
|
149
|
+
const WIDGET_ID = "zero-banner";
|
|
150
|
+
|
|
137
151
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
152
|
+
* Install (or refresh) the banner as a pi-managed widget above the editor.
|
|
153
|
+
*
|
|
154
|
+
* Using `ctx.ui.setWidget` instead of a one-shot `stdout.write` means pi owns
|
|
155
|
+
* the lines and redraws them on every resize, every reload, every session
|
|
156
|
+
* restart — so the banner survives maximize/minimize instead of vanishing into
|
|
157
|
+
* scrollback. The crash this file's earlier comment warned about was the
|
|
158
|
+
* animated 140 ms re-render loop; a static widget set once per `session_start`
|
|
159
|
+
* has no timer and re-uses the same id, so it never spams.
|
|
140
160
|
*/
|
|
141
|
-
|
|
161
|
+
function installWidget(ctx: PiSessionContext): void {
|
|
162
|
+
if (!ctx?.ui || typeof ctx.ui.setWidget !== "function") return;
|
|
163
|
+
if (process.env.NO_COLOR) return;
|
|
164
|
+
const cols = process.stdout?.columns && process.stdout.columns > 0 ? process.stdout.columns : 80;
|
|
165
|
+
ctx.ui.setWidget(WIDGET_ID, bannerBlock(cols));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The pi extension entry point.
|
|
170
|
+
*
|
|
171
|
+
* Hooks `session_start` (fires on startup, reload, new, resume, fork) and
|
|
172
|
+
* installs the banner as a pi-managed widget above the editor — so pi keeps it
|
|
173
|
+
* rendered and redraws it on resize. Disabled with `ZERO_HEADER=off`.
|
|
174
|
+
* Defensive: any failure of registration or the widget install is swallowed —
|
|
175
|
+
* a banner must never break a pi session.
|
|
176
|
+
*/
|
|
177
|
+
export default function register(pi?: unknown): void {
|
|
142
178
|
try {
|
|
143
179
|
if ((process.env.ZERO_HEADER ?? "").trim().toLowerCase() === "off") return;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
180
|
+
if (!pi || typeof (pi as PiAPI).on !== "function") return;
|
|
181
|
+
(pi as PiAPI).on("session_start", (_event, ctx) => {
|
|
182
|
+
try {
|
|
183
|
+
installWidget(ctx);
|
|
184
|
+
} catch {
|
|
185
|
+
// A widget install failure must never break a pi session.
|
|
186
|
+
}
|
|
187
|
+
});
|
|
148
188
|
} catch {
|
|
149
|
-
//
|
|
189
|
+
// Registration itself must never break a pi session.
|
|
150
190
|
}
|
|
151
191
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gonrocca/zero-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
4
4
|
"description": "zero-pi — an installable layer for pi (pi.dev): the zero spec-driven development workflow, per-phase model autotune, and skill auto-learning. Adds capability to pi without modifying pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|