fix(active-memory): use truncateUtf16Safe for log value truncation (#102551)

* fix(active-memory): use truncateUtf16Safe for log value truncation

* fix(active-memory): use truncateUtf16Safe for log value truncation

* test(active-memory): cover UTF-16-safe log limits

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
lsr911 2026-07-09 18:10:42 +08:00 committed by GitHub
parent fc5a4defaf
commit e39e628a84
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 6 additions and 4 deletions

View file

@ -4812,13 +4812,14 @@ describe("active-memory plugin", () => {
).not.toEqual([]);
});
it("caps active-memory log field lengths", async () => {
it("caps active-memory log field lengths without splitting surrogate pairs", async () => {
api.pluginConfig = {
agents: ["main"],
logging: true,
};
plugin.register(api as unknown as OpenClawPluginApi);
const hugeSession = `agent:main:${"x".repeat(500)}`;
const sessionPrefix = `agent:main:${"x".repeat(288)}`;
const hugeSession = `${sessionPrefix}😀tail`;
await hooks.before_prompt_build(
{ prompt: "what wings should i order? long log value", messages: [] },
@ -4836,7 +4837,8 @@ describe("active-memory plugin", () => {
const startLine = infoLines.find((line: string) => line.includes(" start timeoutMs="));
const line = requireNonEmptyString(startLine, "active memory start log line missing");
expect(line.length).toBeLessThan(500);
expect(line).toContain("...");
expect(line).toContain(`session=${sessionPrefix}...`);
expect(line).not.toMatch(/[\uD800-\uDFFF]/u);
});
it("uses a canonical agent session key when only sessionId is available", async () => {

View file

@ -1434,7 +1434,7 @@ function toSingleLineLogValue(value: unknown): string {
.replace(/\s+/g, " ")
.trim();
return singleLine.length > MAX_LOG_VALUE_CHARS
? `${singleLine.slice(0, MAX_LOG_VALUE_CHARS)}...`
? `${truncateUtf16Safe(singleLine, MAX_LOG_VALUE_CHARS)}...`
: singleLine;
}