fix(unicode): 避免标题截断拆开代理对 - #1275
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
deriveSessionTitleFromContent() 在未超长时仍可能返回包含孤立 surrogate 的 non-well-formed 字符串,与 PR 目标的“始终 well-formed”不一致。
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
本 PR 旨在修复用户可见标题/群名在按 UTF-16 code unit 截断时可能切断 surrogate pair(emoji 等 astral 字符)而生成 non-well-formed Unicode、并在 UTF-8 编码时出现替换字符 � 的问题;通过新增统一的截断 helper 并替换关键路径的直接 .slice(0, N) 来保证边界截断结果始终是 well-formed Unicode。
Changes:
- 新增
truncateUtf16WellFormed():按 code point 遍历、以 UTF-16 code unit 计预算,并将孤立 surrogate 归一化为U+FFFD。 - 将会话标题、显式群名、spawn 显式标题、会话重命名标题的截断逻辑替换为新 helper,避免拆开 surrogate pair。
- 增加/扩展单测覆盖 emoji 边界与孤立 surrogate 的修复行为。
File summaries
| File | Description |
|---|---|
| src/utils/unicode.ts | 新增安全截断 helper,避免 surrogate pair 被切断并归一化孤立 surrogate。 |
| src/core/session-create.ts | 在标题/群名派生与 spawn title 解析中替换直接 slice 为安全截断。 |
| src/core/session-board.ts | 在 normalizeSessionTitle() 中替换直接 slice 为安全截断。 |
| test/unicode.test.ts | 新增针对 helper 的预算/emoji/孤立 surrogate 行为测试。 |
| test/session-create.test.ts | 增加标题/群名/spawn title 的 emoji 边界回归测试。 |
| test/session-kanban.test.ts | 增加 session title 归一化在 emoji 边界处保持 well-formed 的回归测试。 |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export function deriveSessionTitleFromContent(content: string): string { | ||
| const firstLine = content.split(/\r?\n/).map(s => s.trim()).find(Boolean) ?? ''; | ||
| if (!firstLine) return t('cmd.createSession.untitled'); | ||
| return firstLine.length > TITLE_MAX ? firstLine.slice(0, TITLE_MAX) + '…' : firstLine; | ||
| return firstLine.length > TITLE_MAX ? truncateUtf16WellFormed(firstLine, TITLE_MAX) + '…' : firstLine; | ||
| } |
新增按 Unicode code point 遍历、按 UTF-16 code unit 计预算的截断 helper,并应用到会话标题、群名和显式标题入口,避免边界 emoji 被编码为替换字符。 Refs: deepcoldy#1253 Co-authored-by: TRAE CLI <noreply@bytedance.com>
993c39f to
d9664f8
Compare
|
你好!这是 Botmux 的自动评审流程。 本 PR 的评审群已创建:https://applink.feishu.cn/client/chat/open?openChatId=oc_442938fc0e50c5db0987038a28e8d171 但你暂时未被拉入群中——你的 GitHub 账号(LPX-E5BD8)不在自动拉群名单里。请把你的 GitHub 账号和飞书信息补进名单文档: 补好后,后续复审会自动把你拉进群。感谢贡献! |
|
🚀 Released in v3.19.3 |
问题
多条标题生成路径直接用
String.slice(0, N)截断。JavaScript 按 UTF-16 code unit 索引,当 emoji 恰好跨越边界时会留下孤立 surrogate,并在 UTF-8 编码时变成替换字符�。Fixes #1253
修复
truncateUtf16WellFormed():按 Unicode code point 遍历,同时以 UTF-16 code unit 计入原有长度预算。U+FFFD归一化,保证返回字符串 well-formed。影响面
验证
wellFormed: false。npx vitest run --project unit test/unicode.test.ts test/session-create.test.ts test/session-kanban.test.ts:53 passed。bun run vitest run --project unit test/unicode.test.ts test/session-create.test.ts test/session-kanban.test.ts:53 passed。bun run build:通过。