fix(linux-node): keep command errors UTF-16 safe (#107717)

This commit is contained in:
Leon-SK668
2026-07-15 00:16:39 -07:00
committed by GitHub
parent 752032e4fb
commit 9a8ed45935
2 changed files with 33 additions and 1 deletions
@@ -0,0 +1,31 @@
import type { SpawnResult } from "openclaw/plugin-sdk/process-runtime";
import { describe, expect, it } from "vitest";
import { assertToolResult, formatToolError } from "./command-utils.js";
const UNPAIRED_SURROGATE_RE =
/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u;
function failedCommand(stderr: string): SpawnResult {
return {
stdout: "",
stderr,
code: 1,
signal: null,
killed: false,
termination: "exit",
};
}
describe("linux-node command utilities", () => {
it("keeps truncated tool errors within the limit without splitting surrogate pairs", () => {
const result = failedCommand(`${"x".repeat(299)}\u{1f600}tail`);
const detail = formatToolError(result);
expect(detail).toBe("x".repeat(299));
expect(detail.length).toBeLessThanOrEqual(300);
expect(UNPAIRED_SURROGATE_RE.test(detail)).toBe(false);
expect(() => assertToolResult(result, "TOOL_UNAVAILABLE")).toThrow(
`TOOL_UNAVAILABLE: ${detail}`,
);
});
});
+2 -1
View File
@@ -1,5 +1,6 @@
import type { OpenClawPluginNodeHostCommandAvailabilityContext } from "openclaw/plugin-sdk/plugin-entry";
import type { CommandOptions, SpawnResult } from "openclaw/plugin-sdk/process-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import {
resolveLinuxNodePluginConfigFromHost,
type ResolvedLinuxNodePluginConfig,
@@ -32,7 +33,7 @@ export function clamp(value: number, minimum: number, maximum: number): number {
export function formatToolError(result: SpawnResult): string {
const detail = result.stderr.trim() || result.stdout.trim();
return detail
? detail.replaceAll(/\s+/gu, " ").slice(0, 300)
? truncateUtf16Safe(detail.replaceAll(/\s+/gu, " "), 300)
: `exit ${result.code ?? "unknown"}`;
}