MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / planFile

Function planFile

src/tools/filesystem/multi-file-edit.ts:52–88  ·  view source on GitHub ↗
(filePath: string, edits: Array<{ old_string: string; new_string: string; replace_all?: boolean }>)

Source from the content-addressed store, hash-verified

50}
51
52async function planFile(filePath: string, edits: Array<{ old_string: string; new_string: string; replace_all?: boolean }>): Promise<EditPlan> {
53 let content: string;
54 try {
55 content = await fs.readFile(filePath, 'utf-8');
56 } catch (e: any) {
57 throw new Error(`Cannot read ${filePath}: ${e?.message ?? e}`);
58 }
59 const original = content;
60 for (let i = 0; i < edits.length; i++) {
61 const edit = edits[i]!;
62 if (edit.replace_all) {
63 // Use split/join to count + replace
64 const parts = content.split(edit.old_string);
65 if (parts.length === 1) {
66 throw new Error(`Edit ${i + 1} in ${filePath}: old_string not found`);
67 }
68 content = parts.join(edit.new_string);
69 } else {
70 const idx = content.indexOf(edit.old_string);
71 if (idx === -1) {
72 throw new Error(`Edit ${i + 1} in ${filePath}: old_string not found`);
73 }
74 const secondIdx = content.indexOf(edit.old_string, idx + 1);
75 if (secondIdx !== -1) {
76 throw new Error(`Edit ${i + 1} in ${filePath}: old_string appears multiple times. Set replace_all=true or extend the context to make it unique.`);
77 }
78 content = content.slice(0, idx) + edit.new_string + content.slice(idx + edit.old_string.length);
79 }
80 }
81 return {
82 path: filePath,
83 originalContent: original,
84 finalContent: content,
85 editCount: edits.length,
86 changed: original !== content,
87 };
88}
89
90export class MultiFileEditTool extends Tool<z.infer<typeof MultiFileEditArgs>> {
91 name = 'multi_file_edit';

Callers 1

executeMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected