fix(auto-reply): keep fallback reason truncation UTF-16 safe (#102631)

* fix(auto-reply): keep fallback reason truncation UTF-16 safe

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(auto-reply): cover UTF-16 fallback truncation

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
maweibin 2026-07-09 20:05:36 +08:00 committed by GitHub
parent a49567cdfd
commit 5b2c316950
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 1 deletions

View file

@ -113,6 +113,15 @@ describe("fallback-state", () => {
expect(resolved.reasonSummary).toContain("Claude Max usage limit reached");
});
it("keeps truncated transient error details UTF-16 safe", () => {
const detail = "x".repeat(68);
const resolved = resolveDemoFallbackTransition({
attempts: [{ ...baseAttempt, error: `429 ${detail}😀tail` }],
});
expect(resolved.reasonSummary).toBe(`HTTP 429: ${detail}`);
});
it("refreshes reason when fallback remains active with same model pair", () => {
const resolved = resolveDemoFallbackTransition({
attempts: [{ ...baseAttempt, reason: "timeout" }],

View file

@ -1,5 +1,6 @@
/** Formats model-fallback notice state for UI/status messages and persisted transition tracking. */
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
import { formatRawAssistantErrorForUi } from "../agents/embedded-agent-helpers.js";
import { areRuntimeModelRefsEquivalent } from "../agents/model-runtime-aliases.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
@ -29,7 +30,7 @@ function truncateFallbackReasonPart(value: string, max = FALLBACK_REASON_PART_MA
if (text.length <= max) {
return text;
}
return `${text.slice(0, Math.max(0, max - 1)).trimEnd()}`;
return `${truncateUtf16Safe(text, max - 1).trimEnd()}`;
}
function formatFallbackAttemptErrorPreview(attempt: RuntimeFallbackAttempt): string | undefined {