Skip to content

Commit f786efd

Browse files
lzyyzznlsteipete
andauthored
fix(cron): keep bounded diagnostics UTF-16 safe (#102624)
* fix(cron): use truncateUtf16Safe for diagnostic entry and summary truncation * test(cron): cover UTF-16 diagnostic boundaries --------- Co-authored-by: Peter Steinberger <[email protected]>
1 parent 5b2c316 commit f786efd

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

src/cron/run-diagnostics.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ describe("cron run diagnostics", () => {
3131
expect(diagnostics?.summary).toHaveLength(2_000);
3232
});
3333

34+
it("keeps bounded diagnostic text valid at UTF-16 boundaries", () => {
35+
const diagnostics = normalizeCronRunDiagnostics({
36+
summary: `${"s".repeat(1_998)}😀tail`,
37+
entries: [
38+
{
39+
ts: 1,
40+
source: "exec",
41+
severity: "error",
42+
message: `${"m".repeat(998)}😀tail`,
43+
},
44+
],
45+
});
46+
47+
expect(diagnostics?.summary).toBe(`${"s".repeat(1_998)}…`);
48+
expect(diagnostics?.entries[0]).toEqual({
49+
ts: 1,
50+
source: "exec",
51+
severity: "error",
52+
message: `${"m".repeat(998)}…`,
53+
truncated: true,
54+
});
55+
});
56+
3457
it("preserves later terminal diagnostics when capping entries", () => {
3558
const diagnostics = normalizeCronRunDiagnostics({
3659
entries: [

src/cron/run-diagnostics.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** Builds bounded, redacted diagnostics for cron run logs and UI surfaces. */
22
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
3+
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
34
import { isToolAllowedByPolicyName } from "../agents/tool-policy-match.js";
45
import { normalizeToolName as normalizePolicyToolName } from "../agents/tool-policy.js";
56
import { getReplyPayloadMetadata } from "../auto-reply/reply-payload.js";
@@ -101,7 +102,7 @@ function normalizeDiagnosticMessage(value: unknown): { message?: string; truncat
101102
if (redacted.length <= MAX_ENTRY_CHARS) {
102103
return { message: redacted };
103104
}
104-
return { message: `${redacted.slice(0, MAX_ENTRY_CHARS - 1)}…`, truncated: true };
105+
return { message: `${truncateUtf16Safe(redacted, MAX_ENTRY_CHARS - 1)}…`, truncated: true };
105106
}
106107

107108
function trimSummary(value: string | undefined): string | undefined {
@@ -112,7 +113,7 @@ function trimSummary(value: string | undefined): string | undefined {
112113
if (normalized.length <= MAX_SUMMARY_CHARS) {
113114
return normalized;
114115
}
115-
return `${normalized.slice(0, MAX_SUMMARY_CHARS - 1)}…`;
116+
return `${truncateUtf16Safe(normalized, MAX_SUMMARY_CHARS - 1)}…`;
116117
}
117118

118119
/** Returns the operator-facing summary for persisted cron diagnostics. */

0 commit comments

Comments
 (0)