File size: 1,596 Bytes
68d7816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import type { TextModel } from './textModel';

export interface EditApplyInput {
  readonly path: string;
  readonly old_string: string;
  readonly new_string: string;
  readonly replace_all: boolean;
}

export type EditApplyResult =
  | { readonly ok: true; readonly rawContent: string; readonly count: number }
  | { readonly ok: false; readonly error: string };

function notFoundMessage(path: string): string {
  return `old_string not found in ${path}, the file contents may be out of date. Please use the Read Tool to reload the content.
`;
}

function notUniqueMessage(path: string, count: number): string {
  return (
    `old_string is not unique in ${path} (found ${String(count)} occurrences). ` +
    'To replace every occurrence, set replace_all=true. To replace only one occurrence, include more surrounding context in old_string.'
  );
}

export class EditService {
  apply(model: TextModel, input: EditApplyInput): EditApplyResult {
    if (input.replace_all) {
      const { text, count } = model.replaceAll(input.old_string, input.new_string);
      if (count === 0) return { ok: false, error: notFoundMessage(input.path) };
      return { ok: true, rawContent: model.materialize(text), count };
    }

    const count = model.countOccurrences(input.old_string);
    if (count === 0) return { ok: false, error: notFoundMessage(input.path) };
    if (count > 1) return { ok: false, error: notUniqueMessage(input.path, count) };

    const text = model.replaceOnce(input.old_string, input.new_string);
    return { ok: true, rawContent: model.materialize(text), count: 1 };
  }
}