// 润色/再沟通 accept 回填:把选中原文替换为产出。选区偏移可能因异步/流式漂移, // 故先按 range 校验,未命中则按原文内容重锚(indexOf)——原文已不存在则返回 null, // 由调用方提示作者重新选择,绝不盲替换(plan §3.3 mustFix)。 export interface SelectionRange { start: number; end: number; } export function applyRefinement( fullText: string, original: string, refined: string, range: SelectionRange, ): string | null { // 选区未漂移:range 处正好是原文 → 原地替换。 if (fullText.slice(range.start, range.end) === original) { return fullText.slice(0, range.start) + refined + fullText.slice(range.end); } // 漂移:按内容重锚,保守取首个匹配。 const idx = fullText.indexOf(original); if (idx === -1) return null; return fullText.slice(0, idx) + refined + fullText.slice(idx + original.length); }