Forráskód Böngészése

fix(editor): preserve literal replacement text

Tianyi Cui 2 hónapja
szülő
commit
fbfe520471

+ 3 - 2
packages/fs/tool-str-replace-editor/src/index.ts

@@ -308,7 +308,8 @@ async function replaceInFile(
   }
   const before = await ctx.fs.readText(target, exec.signal)
   const offsets = matchOffsets(before, oldValue)
-  if (offsets.length === 0) {
+  const offset = offsets[0]
+  if (offset === undefined) {
     throw new FsError(
       `No replacement was performed, old_str \`${oldValue}\` did not appear verbatim in ${target.displayPath}.`,
       'FS_EDIT_NOT_FOUND',
@@ -325,7 +326,7 @@ async function replaceInFile(
   try {
     outcome = await ctx.fs.writeText(
       target,
-      before.replace(oldValue, newValue),
+      before.slice(0, offset) + newValue + before.slice(offset + oldValue.length),
       intent === undefined
         ? { kind: 'replaceIfVersion', version: info.version }
         : { kind: 'replaceIfVersion', version: intent.version },

+ 15 - 0
packages/fs/tool-str-replace-editor/tests/tools.spec.ts

@@ -194,6 +194,21 @@ describe('tool-str-replace-editor', () => {
     expect(await readFile(sample, 'utf8')).toBe('one\nbetween\n\nthree\n')
   })
 
+  it('writes replacement text literally', async () => {
+    const { ctx, root, owner } = await setup()
+    const sample = join(root, 'literal.txt')
+    const replacement = "$&|$`|$'|$$"
+    await writeFile(sample, 'before OLD after')
+
+    expect((await call(ctx, owner, {
+      command: 'str_replace',
+      path: sample,
+      old_str: 'OLD',
+      new_str: replacement,
+    })).isError).toBe(false)
+    expect(await readFile(sample, 'utf8')).toBe(`before ${replacement} after`)
+  })
+
   it('lists visible entries to depth two and clips at the configured view limit', async () => {
     const { ctx, root, owner } = await setup({ maxOutputChars: 10_000 })
     await mkdir(join(root, 'dir', 'nested', 'third'), { recursive: true })