diff --git a/src/core/hooks/auto-recall.ts b/src/core/hooks/auto-recall.ts index e5760f0..036c1cd 100644 --- a/src/core/hooks/auto-recall.ts +++ b/src/core/hooks/auto-recall.ts @@ -776,11 +776,15 @@ function normalizeBudgetLimit(value: number | undefined): number | undefined { } function truncateRecallLine(line: string, maxChars: number): string { - if (line.length <= maxChars) return line; + // Count and slice by code point, not UTF-16 code unit, so a cut never lands + // between the halves of a surrogate pair (which would corrupt a non-BMP + // character to U+FFFD when the line is UTF-8 encoded for the request). + const cps = Array.from(line); + if (cps.length <= maxChars) return line; if (maxChars <= RECALL_TRUNCATION_SUFFIX.length) { - return line.slice(0, maxChars); + return cps.slice(0, maxChars).join(""); } - return `${line.slice(0, maxChars - RECALL_TRUNCATION_SUFFIX.length).trimEnd()}${RECALL_TRUNCATION_SUFFIX}`; + return `${cps.slice(0, maxChars - RECALL_TRUNCATION_SUFFIX.length).join("").trimEnd()}${RECALL_TRUNCATION_SUFFIX}`; } /**