Skip to content

Commit e138649

Browse files
authored
fix(tasks): preserve terminal column width
1 parent 2a22402 commit e138649

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

src/commands/tasks.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type { OpenClawTestState } from "../test-utils/openclaw-test-state.js";
2424
import {
2525
tasksAuditCommand,
2626
tasksCancelCommand,
27+
tasksListCommand,
2728
tasksMaintenanceCommand,
2829
tasksShowCommand,
2930
} from "./tasks.js";
@@ -601,6 +602,30 @@ describe("tasks commands", () => {
601602
});
602603
});
603604

605+
it("keeps task list summaries within their UTF-16 column limit", async () => {
606+
await withTaskCommandStateDir(async () => {
607+
createTaskRecord({
608+
runtime: "cli",
609+
ownerKey: "agent:main:main",
610+
scopeKind: "session",
611+
runId: "task-utf16-summary",
612+
status: "succeeded",
613+
task: "Inspect task summary",
614+
terminalSummary: `${"y".repeat(78)}🚀xx`,
615+
});
616+
const runtime = createRuntime();
617+
618+
await tasksListCommand({}, runtime);
619+
620+
const output = vi
621+
.mocked(runtime.log)
622+
.mock.calls.map(([line]) => String(line))
623+
.join("\n");
624+
expect(output).toContain(`${"y".repeat(78)}…`);
625+
expect(output).not.toContain("🚀");
626+
});
627+
});
628+
604629
it("explains retained lost task cleanup timing in maintenance text output", async () => {
605630
await withTaskCommandStateDir(async () => {
606631
const cleanupAfter = Date.now() + 60_000;

src/commands/tasks.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { timestampMsToIsoString } from "@openclaw/normalization-core/number-coercion";
55
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
6+
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
67
import { isRich, theme } from "../../packages/terminal-core/src/theme.js";
78
import { formatCliCommand } from "../cli/command-format.js";
89
import { formatLookupMiss } from "../cli/error-format.js";
@@ -205,12 +206,7 @@ function truncate(value: string, maxChars: number) {
205206
if (value.length <= maxChars) {
206207
return value;
207208
}
208-
if (maxChars <= 1) {
209-
return value.slice(0, maxChars);
210-
}
211-
return `${Array.from(value)
212-
.slice(0, maxChars - 1)
213-
.join("")}…`;
209+
return maxChars <= 0 ? "" : `${truncateUtf16Safe(value, maxChars - 1)}…`;
214210
}
215211

216212
function shortToken(value: string | undefined, maxChars = ID_PAD): string {

0 commit comments

Comments
 (0)