pi-zentui 0.29.2 → 0.29.3
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.
|
@@ -336,9 +336,9 @@ export default function (pi: ExtensionAPI, host: ZentuiHost = {}) {
|
|
|
336
336
|
return undefined;
|
|
337
337
|
}
|
|
338
338
|
};
|
|
339
|
-
// Layered visibility
|
|
340
|
-
// Data, demand, and timer consumers
|
|
341
|
-
//
|
|
339
|
+
// Layered visibility does not grant installation ownership: editor install/restore stays exclusive.
|
|
340
|
+
// Data, demand, and timer consumers use these helpers; Working-line placement additionally
|
|
341
|
+
// requires focused, rendered border capability before its controller hides its own host row.
|
|
342
342
|
// Ownership counts before Pi constructs its editor; layered visibility requires the recorded
|
|
343
343
|
// instance to remain reachable through the current factory.
|
|
344
344
|
const layeredVisibleEditor = () => layeredEditor.editorVisibleThrough(currentEditorFactory());
|
|
@@ -402,17 +402,13 @@ export default function (pi: ExtensionAPI, host: ZentuiHost = {}) {
|
|
|
402
402
|
undefined,
|
|
403
403
|
(ctx) => {
|
|
404
404
|
if (!activeTuiContext || ctx.ui !== activeTuiContext.ui) return false;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
405
|
+
// Factory visibility alone is insufficient: the current focused editor must have
|
|
406
|
+
// rendered safe border geometry before the separately owned Working row can hide.
|
|
409
407
|
return Boolean(
|
|
410
|
-
|
|
411
|
-
sessionLifecycle.isCurrent(activeEditor.generation) &&
|
|
412
|
-
activeEditor.factory === installedEditorFactory &&
|
|
408
|
+
sessionLifecycle.isCurrent() &&
|
|
413
409
|
effectiveEditorEnabled() &&
|
|
414
410
|
currentConfig.components.editor.style !== "accent-rail" &&
|
|
415
|
-
|
|
411
|
+
visibleEditor()?.canEmbedWorkingLineBorder(),
|
|
416
412
|
);
|
|
417
413
|
},
|
|
418
414
|
);
|
|
@@ -939,10 +935,7 @@ export default function (pi: ExtensionAPI, host: ZentuiHost = {}) {
|
|
|
939
935
|
return observed;
|
|
940
936
|
};
|
|
941
937
|
|
|
942
|
-
//
|
|
943
|
-
const isActiveEditor = (editor: PolishedEditor | WrappedPolishedEditor, generation: number) =>
|
|
944
|
-
sessionLifecycle.isCurrent(generation) && activeEditor?.editor === editor;
|
|
945
|
-
// Read-only: also true for an editor still visible beneath a foreign wrapper.
|
|
938
|
+
// Also true for an editor still visible beneath a foreign wrapper; installation stays exclusive.
|
|
946
939
|
const isVisibleEditor = (editor: PolishedEditor | WrappedPolishedEditor, generation: number) =>
|
|
947
940
|
sessionLifecycle.isCurrent(generation) && visibleEditor() === editor;
|
|
948
941
|
|
|
@@ -950,7 +943,7 @@ export default function (pi: ExtensionAPI, host: ZentuiHost = {}) {
|
|
|
950
943
|
editor: PolishedEditor | WrappedPolishedEditor,
|
|
951
944
|
generation: number,
|
|
952
945
|
) => {
|
|
953
|
-
if (!
|
|
946
|
+
if (!isVisibleEditor(editor, generation) || !activeTuiContext || !workingLineSessionReady)
|
|
954
947
|
return;
|
|
955
948
|
if (!host.skinOnly) workingLine.reconcile(activeTuiContext);
|
|
956
949
|
if (workingLine.isAvailable()) requestEditorRepaint();
|
|
@@ -966,10 +959,12 @@ export default function (pi: ExtensionAPI, host: ZentuiHost = {}) {
|
|
|
966
959
|
const editorWorkingLineFrame = (
|
|
967
960
|
editor: PolishedEditor | WrappedPolishedEditor,
|
|
968
961
|
generation: number,
|
|
969
|
-
) =>
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
962
|
+
) => {
|
|
963
|
+
if (host.skinOnly || !sessionLifecycle.isCurrent(generation)) return undefined;
|
|
964
|
+
// Even a stale instance render must release a row whose current border disappeared.
|
|
965
|
+
const frame = workingLine.currentWorkingLineFrame();
|
|
966
|
+
return isVisibleEditor(editor, generation) ? frame : undefined;
|
|
967
|
+
};
|
|
973
968
|
|
|
974
969
|
/** Records a freshly constructed editor as owned (exclusive) or visible beneath a foreign wrapper. */
|
|
975
970
|
const registerConstructedEditor = (
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* and redraw requests. The record is valid only while the outer factory observed at construction is
|
|
9
9
|
* still the current editor factory, so any replacement of the chain invalidates it.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Construction alone cannot authorize hiding the Working row: its controller additionally requires
|
|
12
|
+
* a focused editor that has rendered safe border geometry. A wrapper that renders then discards those
|
|
13
|
+
* rows remains undetectable; supporting such wrappers requires an explicit host visibility contract.
|
|
14
14
|
*/
|
|
15
15
|
export class LayeredEditorConsumer<Factory, Editor = unknown> {
|
|
16
16
|
private record?: {
|
|
@@ -172,9 +172,11 @@ function renderTopLeft(
|
|
|
172
172
|
metadata: MinimalistEditorMetadata,
|
|
173
173
|
uiTheme: Theme,
|
|
174
174
|
config: ZentuiConfig,
|
|
175
|
+
renderBorder: (text: string) => string,
|
|
175
176
|
includeSessionName = true,
|
|
176
177
|
): string {
|
|
177
178
|
const source = config.components.editor.colorSource;
|
|
179
|
+
const separator = safeThemeFg(uiTheme, "muted", " · ");
|
|
178
180
|
const bashMode = bashModeLabel(inputText);
|
|
179
181
|
const parts: string[] = [];
|
|
180
182
|
if (bashMode) {
|
|
@@ -206,16 +208,20 @@ function renderTopLeft(
|
|
|
206
208
|
? sanitizeEditorMetadataText(metadata.sessionName ?? "")
|
|
207
209
|
: "";
|
|
208
210
|
if (config.components.editor.styles.minimalist.showSessionName && sessionName) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
return joinStyled(
|
|
212
|
+
[
|
|
213
|
+
joinStyled(parts, separator),
|
|
214
|
+
renderStyleForSource(
|
|
215
|
+
uiTheme,
|
|
216
|
+
source,
|
|
217
|
+
componentColor(config, "editor", "sessionName"),
|
|
218
|
+
sessionName,
|
|
219
|
+
),
|
|
220
|
+
],
|
|
221
|
+
metadata.workingLineFrame ? renderBorder(" ─ ") : separator,
|
|
216
222
|
);
|
|
217
223
|
}
|
|
218
|
-
return joinStyled(parts,
|
|
224
|
+
return joinStyled(parts, separator);
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
function renderTopRight(
|
|
@@ -448,6 +454,7 @@ function renderTemplateBuiltin(
|
|
|
448
454
|
{ cwd: "", sessionName: metadata.sessionName },
|
|
449
455
|
uiTheme,
|
|
450
456
|
explicitConfig,
|
|
457
|
+
renderBorder,
|
|
451
458
|
);
|
|
452
459
|
case "turn_duration":
|
|
453
460
|
return renderTopLeft(
|
|
@@ -455,6 +462,7 @@ function renderTemplateBuiltin(
|
|
|
455
462
|
{ cwd: "", agentDurationMs: metadata.agentDurationMs, agentActive: metadata.agentActive },
|
|
456
463
|
uiTheme,
|
|
457
464
|
explicitConfig,
|
|
465
|
+
renderBorder,
|
|
458
466
|
);
|
|
459
467
|
case "model":
|
|
460
468
|
isolated.modelLabel = metadata.modelLabel;
|
|
@@ -693,8 +701,8 @@ export function renderMinimalistFrame({
|
|
|
693
701
|
if (!count || !/^[1-9]\d*$/.test(count)) return "";
|
|
694
702
|
return safeThemeFg(uiTheme, "muted", `${direction === "above" ? "↑" : "↓"} ${count} more`);
|
|
695
703
|
};
|
|
696
|
-
const topMetadata = renderTopLeft(inputText, metadata, uiTheme, config);
|
|
697
|
-
const topOperational = renderTopLeft(inputText, metadata, uiTheme, config, false);
|
|
704
|
+
const topMetadata = renderTopLeft(inputText, metadata, uiTheme, config, renderBorder);
|
|
705
|
+
const topOperational = renderTopLeft(inputText, metadata, uiTheme, config, renderBorder, false);
|
|
698
706
|
const topViewport = viewportLabel("above", viewport?.above);
|
|
699
707
|
const topLeft = joinStyled([topViewport, topMetadata], separator);
|
|
700
708
|
const topRightBudget = Math.max(0, width - 8 - visibleWidth(topLeft));
|
|
@@ -775,6 +783,7 @@ export function renderMinimalistFrame({
|
|
|
775
783
|
{ cwd: "", workingLineFrame: metadata.workingLineFrame },
|
|
776
784
|
uiTheme,
|
|
777
785
|
config,
|
|
786
|
+
renderBorder,
|
|
778
787
|
false,
|
|
779
788
|
)
|
|
780
789
|
: "";
|
|
@@ -784,13 +793,18 @@ export function renderMinimalistFrame({
|
|
|
784
793
|
if (visibleWidth(prefix) > budget) prefix = operational;
|
|
785
794
|
if (visibleWidth(prefix) > budget)
|
|
786
795
|
prefix = truncateToWidth(prefix, Math.max(0, budget), "…");
|
|
796
|
+
const metadataSeparator =
|
|
797
|
+
operational && metadata.workingLineFrame ? renderBorder(" ─ ") : separator;
|
|
787
798
|
rendered = renderMinimalistTemplate(
|
|
788
799
|
format,
|
|
789
800
|
resolve,
|
|
790
801
|
customNames,
|
|
791
|
-
Math.max(
|
|
802
|
+
Math.max(
|
|
803
|
+
0,
|
|
804
|
+
budget - visibleWidth(prefix) - (prefix ? visibleWidth(metadataSeparator) : 0),
|
|
805
|
+
),
|
|
792
806
|
);
|
|
793
|
-
return joinStyled([prefix, rendered],
|
|
807
|
+
return joinStyled([prefix, rendered], metadataSeparator);
|
|
794
808
|
}
|
|
795
809
|
switch (slot) {
|
|
796
810
|
case "topLeft": {
|
|
@@ -179,18 +179,20 @@ function nativeMarkdown(instance: PatchableUserMessagePrototype):
|
|
|
179
179
|
}
|
|
180
180
|
const children = direct;
|
|
181
181
|
if (!Array.isArray(children) || children.length !== 1) return undefined;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
// Pi >=1.0 holds the Markdown directly (it pads/colors itself); older Pi
|
|
183
|
+
// wrapped it in a Box. Accept both shapes.
|
|
184
|
+
let renderer = children[0];
|
|
185
|
+
const direct1 = isNativeMarkdown(renderer);
|
|
186
|
+
if (isRecord(renderer) && !direct1) {
|
|
187
|
+
const box = renderer;
|
|
188
|
+
if (!Array.isArray(box.children) || box.children.length !== 1) return undefined;
|
|
189
|
+
renderer = box.children[0];
|
|
190
|
+
}
|
|
185
191
|
if (!isNativeMarkdown(renderer)) return undefined;
|
|
186
192
|
const child = renderer as unknown as Record<string, unknown>;
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
child.paddingY !== 0 ||
|
|
191
|
-
!isRecord(child.theme)
|
|
192
|
-
)
|
|
193
|
-
return undefined;
|
|
193
|
+
if (typeof child.text !== "string" || !isRecord(child.theme)) return undefined;
|
|
194
|
+
// Box-wrapped (older Pi) Markdown must be unpadded; Pi >=1.0 pads it itself.
|
|
195
|
+
if (!direct1 && (child.paddingX !== 0 || child.paddingY !== 0)) return undefined;
|
|
194
196
|
for (const key of [
|
|
195
197
|
"heading",
|
|
196
198
|
"link",
|
|
@@ -217,6 +219,8 @@ function nativeMarkdown(instance: PatchableUserMessagePrototype):
|
|
|
217
219
|
)
|
|
218
220
|
return undefined;
|
|
219
221
|
if (child.defaultTextStyle !== undefined && !isRecord(child.defaultTextStyle)) return undefined;
|
|
222
|
+
// Pi >=1.0 puts the message background in defaultTextStyle; Zentui frames draw their own.
|
|
223
|
+
const { bgColor: _bg, ...textStyle } = (child.defaultTextStyle ?? {}) as Record<string, unknown>;
|
|
220
224
|
return {
|
|
221
225
|
renderer: renderer as unknown as Markdown,
|
|
222
226
|
text: child.text,
|
|
@@ -224,9 +228,9 @@ function nativeMarkdown(instance: PatchableUserMessagePrototype):
|
|
|
224
228
|
theme: child.theme as unknown as NonNullable<
|
|
225
229
|
UserMessageStyleRenderInput["markdown"]
|
|
226
230
|
>["theme"],
|
|
227
|
-
defaultTextStyle: child.defaultTextStyle
|
|
228
|
-
|
|
229
|
-
|
|
231
|
+
defaultTextStyle: (child.defaultTextStyle === undefined
|
|
232
|
+
? undefined
|
|
233
|
+
: textStyle) as NonNullable<UserMessageStyleRenderInput["markdown"]>["defaultTextStyle"],
|
|
230
234
|
options: child.options as NonNullable<UserMessageStyleRenderInput["markdown"]>["options"],
|
|
231
235
|
},
|
|
232
236
|
};
|
package/package.json
CHANGED