From c9bb5a93f0ea652e798ca419ed39cf182fc2c4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 23 Sep 2026 11:55:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=9A=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E5=BC=95=E7=94=A8=E5=90=8D=E5=BD=92=E4=B8=80=E5=8C=96=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E6=92=9E=E5=90=8D=EF=BC=8C=E4=BB=A5=E5=8F=8A=E7=A2=B0?= =?UTF-8?q?=E6=92=9E=E7=9B=AE=E5=89=8D=E5=8F=AA=E5=9C=A8=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E4=BE=A7=E5=85=9C=E4=BD=8F=20normalizeMentionName=20=E7=9A=84?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E8=A1=A5=E4=B8=8A=E3=80=8C=E5=BD=92=E4=B8=80?= =?UTF-8?q?=E5=8C=96=E4=B8=8D=E4=BF=9D=E8=AF=81=E5=90=8D=E5=AD=97=E5=94=AF?= =?UTF-8?q?=E4=B8=80=E3=80=8D=EF=BC=9A`hero=20v2`=20=E4=B8=8E=20`hero-v2`?= =?UTF-8?q?=20=E6=8A=98=E6=88=90=E5=90=8C=E4=B8=80=E4=B8=AA=20token?= =?UTF-8?q?=EF=BC=8C=E5=80=99=E9=80=89=E8=8F=9C=E5=8D=95=E4=BE=A7=E4=B8=8D?= =?UTF-8?q?=E5=81=9A=E5=86=B2=E7=AA=81=E6=A3=80=E6=B5=8B=E3=80=81=E4=BC=9A?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=90=8C=E4=B8=80=E4=B8=AA=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=EF=BC=8C=E7=A2=B0=E6=92=9E=E7=94=B1=20buildContentFromPastedTe?= =?UTF-8?q?xt=20=E7=9A=84=E3=80=8C=E5=90=8C=E5=90=8D=E5=A4=9A=E5=80=99?= =?UTF-8?q?=E9=80=89=E4=B8=80=E5=BE=8B=E6=8C=89=E6=96=87=E6=9C=AC=E4=BF=9D?= =?UTF-8?q?=E7=95=99=E3=80=8D=E5=85=9C=E4=BD=8F=20=E5=90=8C=E6=AD=A5=20AGC?= =?UTF-8?q?=20=E8=81=8A=E5=A4=A9=E7=B4=A0=E6=9D=90=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E8=AF=B4=E6=98=8E=E7=9A=84=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E5=90=8D=E7=A9=BA=E7=99=BD=E4=B8=8D=E5=8F=98=E9=87=8F=E5=B0=8F?= =?UTF-8?q?=E8=8A=82=EF=BC=8C=E5=86=99=E6=98=8E=E8=BF=99=E6=98=AF=E5=B7=B2?= =?UTF-8?q?=E7=9F=A5=E6=AE=8B=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/project-workspace/resourceReferences.ts | 4 ++++ docs/【功能说明】AGC聊天素材引用-2026-09-08.md | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/resourceReferences.ts b/apps/ai-game-creator-shell/src/features/project-workspace/resourceReferences.ts index 08bfe5250..440e70d6b 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/resourceReferences.ts +++ b/apps/ai-game-creator-shell/src/features/project-workspace/resourceReferences.ts @@ -165,6 +165,10 @@ export function resourceLabelResolver( * * 这里只做归一化、不做 `resourceId` 之类的兜底:兜底属于名字的来源侧(例如 * `resourceDisplayName` 在文件名词干为空时回退 `asset.id`),归一化本身保持是个纯函数。 + * + * 归一化不保证名字唯一:`hero v2` 与 `hero-v2` 会折成同一个 token,两条引用因此在候选菜单里 + * 显示同一个标签。归一化后的碰撞由 `buildContentFromPastedText` 的「同名多候选一律按文本保留」 + * 兜住(不认错,但两者都成不了 chip);候选菜单侧不做冲突检测,标签重复是这条取舍的可见残留。 */ export function normalizeMentionName(value: string) { return value.trim().replace(/\s+/gu, '-'); diff --git a/docs/【功能说明】AGC聊天素材引用-2026-09-08.md b/docs/【功能说明】AGC聊天素材引用-2026-09-08.md index b91a0eee4..3bbd8ac33 100644 --- a/docs/【功能说明】AGC聊天素材引用-2026-09-08.md +++ b/docs/【功能说明】AGC聊天素材引用-2026-09-08.md @@ -50,6 +50,7 @@ AGC 聊天输入框支持以结构化引用标记当前项目已登记素材, - 归一化落在名字的产生处:`resourceDisplayName()`(素材显示名由文件名派生)、Skill 目录读入与 `toReference` / `mentionToken`、附件导入映射与 `toReference` / `mentionToken`、以及两个 token 投影(`chatReferenceMentionToken`、`directCodexContentToPromptText`)。token 层再折一次是幂等的,因此「token 里绝不会有空白」是这一层的性质,不依赖上游数据干净。 - 为什么必须有这条不变量:token 的边界规则是「前后为空白或行首行尾」。名字里带空白时,`@hero v2` 会被反解析切成 `@hero` + 文本 `v2`,短名字抢先命中,真正的引用反而被当成孤儿补到正文末尾(粘贴回填会多出一枚错芯片)。折成 `-` 之后 token 自带边界,`@hero` 不会命中 `@hero-v2`(后一个字符是 `-`)。 - 词干为空的素材名回退 `asset.id`:整名就是扩展名时(`.env` / `.gitignore`)文件名去掉扩展名会得到空串,空名字会让 token 退化成只有触发符的裸 `@`——候选菜单里是一枚空芯片,粘贴解析还会拿它认领正文里任何一处裸 `@`。所以 `resourceDisplayName()` 在这一种情况下回退 `asset.id`,回退值同样过一遍 `normalizeMentionName`;`normalizeMentionName` 自身仍然只做归一化、不做兜底。 +- 归一化不保证名字唯一:`hero v2` 与 `hero-v2` 会折成同一个 token,候选菜单里两条候选显示同一个标签,从气泡复制出来的那段文字也重建不成芯片(解析侧按「同名多候选一律按文本保留」处理,不认错)。菜单侧目前不做冲突检测,这是这条不变量的已知残留。 - 已存在的老文本(本次改动前生成的回合 prompt、历史气泡)里的 `@hero v2` 不再解析——粘贴时按字面保留,重试 / 润色回填时该引用会退化成末尾孤儿。内容不丢,位置可能不对。 ## 拖拽引用(2026-09-21)