fix(terminal): stabilize skills table width across Terminal.app and iTerm (#42849)

* Terminal: measure grapheme display width

* Tests: cover grapheme terminal width

* Terminal: wrap table cells by grapheme width

* Tests: cover emoji table alignment

* Terminal: refine table wrapping and width handling

* Terminal: stop shrinking CLI tables by one column

* Skills: use Terminal-safe emoji in list output

* Changelog: note terminal skills table fixes

* Skills: normalize emoji presentation across outputs

* Terminal: consume unsupported escape bytes in tables
This commit is contained in:
Vincent Koc
2026-03-11 09:13:10 -04:00
committed by GitHub
parent 10e6e27451
commit 04e103d10e
32 changed files with 299 additions and 67 deletions

View File

@@ -4,7 +4,7 @@ import type { OutboundDeliveryResult } from "../infra/outbound/deliver.js";
import { formatGatewaySummary, formatOutboundDeliverySummary } from "../infra/outbound/format.js";
import type { MessageActionRunResult } from "../infra/outbound/message-action-runner.js";
import { formatTargetDisplay } from "../infra/outbound/target-resolver.js";
import { renderTable } from "../terminal/table.js";
import { getTerminalTableWidth, renderTable } from "../terminal/table.js";
import { isRich, theme } from "../terminal/theme.js";
import { shortenText } from "./text-format.js";
@@ -257,7 +257,7 @@ export function formatMessageCliText(result: MessageActionRunResult): string[] {
const muted = (text: string) => (rich ? theme.muted(text) : text);
const heading = (text: string) => (rich ? theme.heading(text) : text);
const width = Math.max(60, (process.stdout.columns ?? 120) - 1);
const width = getTerminalTableWidth();
const opts: FormatOpts = { width };
if (result.handledBy === "dry-run") {

View File

@@ -38,7 +38,7 @@ import {
} from "../../infra/provider-usage.js";
import { getShellEnvAppliedKeys, shouldEnableShellEnvFallback } from "../../infra/shell-env.js";
import type { RuntimeEnv } from "../../runtime.js";
import { renderTable } from "../../terminal/table.js";
import { getTerminalTableWidth, renderTable } from "../../terminal/table.js";
import { colorize, theme } from "../../terminal/theme.js";
import { shortenHomePath } from "../../utils.js";
import { resolveProviderAuthOverview } from "./list.auth-overview.js";
@@ -631,7 +631,7 @@ export async function modelsStatusCommand(
if (probeSummary.results.length === 0) {
runtime.log(colorize(rich, theme.muted, "- none"));
} else {
const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);
const tableWidth = getTerminalTableWidth();
const sorted = sortProbeResults(probeSummary.results);
const statusColor = (status: string) => {
if (status === "ok") {

View File

@@ -1,5 +1,5 @@
import type { ProgressReporter } from "../../cli/progress.js";
import { renderTable } from "../../terminal/table.js";
import { getTerminalTableWidth, renderTable } from "../../terminal/table.js";
import { isRich, theme } from "../../terminal/theme.js";
import { groupChannelIssuesByChannel } from "./channel-issues.js";
import { appendStatusAllDiagnosis } from "./diagnosis.js";
@@ -57,7 +57,7 @@ export async function buildStatusAllReportLines(params: {
const fail = (text: string) => (rich ? theme.error(text) : text);
const muted = (text: string) => (rich ? theme.muted(text) : text);
const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);
const tableWidth = getTerminalTableWidth();
const overview = renderTable({
width: tableWidth,

View File

@@ -16,7 +16,7 @@ import {
} from "../memory/status-format.js";
import type { RuntimeEnv } from "../runtime.js";
import { runSecurityAudit } from "../security/audit.js";
import { renderTable } from "../terminal/table.js";
import { getTerminalTableWidth, renderTable } from "../terminal/table.js";
import { theme } from "../terminal/theme.js";
import { formatHealthChannelLines, type HealthSummary } from "./health.js";
import { resolveControlUiLinks } from "./onboard-helpers.js";
@@ -229,7 +229,7 @@ export async function statusCommand(
runtime.log("");
}
const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);
const tableWidth = getTerminalTableWidth();
if (secretDiagnostics.length > 0) {
runtime.log(theme.warn("Secret diagnostics:"));