diff --git a/packages/pi-tui/src/utils.ts b/packages/pi-tui/src/utils.ts index 430710aed..180221db4 100644 --- a/packages/pi-tui/src/utils.ts +++ b/packages/pi-tui/src/utils.ts @@ -85,7 +85,12 @@ export function extractAnsiCode(str: string, pos: number): { code: string; lengt * Delegates to the native Rust implementation. */ export function visibleWidth(str: string): number { - return nativeVisibleWidth(str); + try { + return nativeVisibleWidth(str); + } catch { + // JS fallback — strip ANSI codes and return length (#1418) + return str.replace(/\x1b\[[0-9;]*m/g, "").length; + } } /** @@ -97,7 +102,28 @@ export function visibleWidth(str: string): number { * @returns Array of wrapped lines (NOT padded to width) */ export function wrapTextWithAnsi(text: string, width: number): string[] { - return nativeWrapTextWithAnsi(text, width); + try { + return nativeWrapTextWithAnsi(text, width); + } catch { + // JS fallback when native addon is unavailable (e.g., glibc mismatch on older Linux) (#1418) + const lines: string[] = []; + for (const line of text.split("\n")) { + if (line.length <= width) { + lines.push(line); + } else { + // Simple word-wrap without ANSI awareness + let remaining = line; + while (remaining.length > width) { + const breakAt = remaining.lastIndexOf(" ", width); + const splitPoint = breakAt > 0 ? breakAt : width; + lines.push(remaining.slice(0, splitPoint)); + remaining = remaining.slice(splitPoint).trimStart(); + } + if (remaining) lines.push(remaining); + } + } + return lines; + } } /**