mirror of
https://github.com/lukaszraczylo/filepuff-mcp.git
synced 2026-10-12 04:54:27 +00:00
fix(util): rune-safe truncation across formatters
firstLineOf (query) and truncateString (edit) sliced strings at a raw byte offset, splitting a multibyte UTF-8 character into invalid bytes in LLM-facing output (ast_query compact format and edit not-found errors are hot paths). Extract the rune-boundary backoff already used by search's truncateLine into util.RuneBoundary and route all three sites through it. Adds table-driven tests for the primitive and a multibyte case for firstLineOf.
This commit is contained in:
@@ -186,6 +186,9 @@ func TestFirstLineOf(t *testing.T) {
|
||||
{"line1\nline2", 20, "line1"},
|
||||
{"\n\nfoo", 20, "foo"},
|
||||
{"abcdefghij", 5, "abcd…"},
|
||||
// Multibyte: "ααα" is 6 bytes (each α = 2). maxLen-1 = 3 lands inside the
|
||||
// 2nd α; must back off to a rune boundary, never split into invalid UTF-8.
|
||||
{"ααα", 4, "α…"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got := firstLineOf(c.input, c.maxLen)
|
||||
|
||||
@@ -583,7 +583,7 @@ func firstLineOf(s string, maxLen int) string {
|
||||
continue
|
||||
}
|
||||
if len(line) > maxLen {
|
||||
return line[:maxLen-1] + "…"
|
||||
return line[:util.RuneBoundary(line, maxLen-1)] + "…"
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user