Skip to content

Commit d2d44e7

Browse files
authored
Merge pull request #195 from drivecore/feature/allow-texteditor-overwrite
feat: allow textEditor to overwrite existing files with create command
2 parents 6f2ce28 + d1cde65 commit d2d44e7

File tree

2 files changed

+109
-12
lines changed

2 files changed

+109
-12
lines changed

packages/agent/src/tools/io/textEditor.test.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,4 +303,94 @@ describe('textEditor', () => {
303303
);
304304
}).rejects.toThrow(/Found 2 occurrences/);
305305
});
306+
307+
it('should overwrite an existing file with create command', async () => {
308+
const initialContent = 'Initial content';
309+
const newContent = 'New content that overwrites the file';
310+
const testPath = join(testDir, `${randomUUID()}.txt`);
311+
312+
// Create initial file
313+
await textEditorTool.execute(
314+
{
315+
command: 'create',
316+
path: testPath,
317+
file_text: initialContent,
318+
description: 'test',
319+
},
320+
toolContext,
321+
);
322+
323+
// Verify initial content
324+
let content = await readFile(testPath, 'utf8');
325+
expect(content).toBe(initialContent);
326+
327+
// Overwrite the file using create command
328+
const result = await textEditorTool.execute(
329+
{
330+
command: 'create',
331+
path: testPath,
332+
file_text: newContent,
333+
description: 'test',
334+
},
335+
toolContext,
336+
);
337+
338+
// Verify return value
339+
expect(result.success).toBe(true);
340+
expect(result.message).toContain('File overwritten');
341+
342+
// Verify content has been updated
343+
content = await readFile(testPath, 'utf8');
344+
expect(content).toBe(newContent);
345+
});
346+
347+
it('should be able to undo file overwrite', async () => {
348+
const initialContent = 'Initial content that will be restored';
349+
const overwrittenContent = 'This content will be undone';
350+
const testPath = join(testDir, `${randomUUID()}.txt`);
351+
352+
// Create initial file
353+
await textEditorTool.execute(
354+
{
355+
command: 'create',
356+
path: testPath,
357+
file_text: initialContent,
358+
description: 'test',
359+
},
360+
toolContext,
361+
);
362+
363+
// Overwrite the file
364+
await textEditorTool.execute(
365+
{
366+
command: 'create',
367+
path: testPath,
368+
file_text: overwrittenContent,
369+
description: 'test',
370+
},
371+
toolContext,
372+
);
373+
374+
// Verify overwritten content
375+
let content = await readFile(testPath, 'utf8');
376+
expect(content).toBe(overwrittenContent);
377+
378+
// Undo the overwrite
379+
const result = await textEditorTool.execute(
380+
{
381+
command: 'undo_edit',
382+
path: testPath,
383+
description: 'test',
384+
},
385+
toolContext,
386+
);
387+
388+
// Verify return value
389+
expect(result.success).toBe(true);
390+
expect(result.message).toContain('Successfully reverted');
391+
392+
// Verify content is back to initial
393+
content = await readFile(testPath, 'utf8');
394+
expect(content).toBe(initialContent);
395+
});
306396
});

packages/agent/src/tools/io/textEditor.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,29 +160,36 @@ export const textEditorTool: Tool<Parameters, ReturnType> = {
160160
}
161161

162162
case 'create': {
163-
// Check if file already exists
164-
if (fsSync.existsSync(absolutePath)) {
165-
throw new Error(
166-
`File already exists: ${filePath}. Use str_replace to modify it.`,
167-
);
168-
}
169-
170163
if (!file_text) {
171164
throw new Error('file_text parameter is required for create command');
172165
}
173166

174167
// Create parent directories if they don't exist
175168
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
176169

177-
// Create the file
178-
await fs.writeFile(absolutePath, file_text, 'utf8');
170+
// Check if file already exists
171+
const fileExists = fsSync.existsSync(absolutePath);
179172

180-
// Store initial state for undo
181-
fileStateHistory[absolutePath] = [file_text];
173+
if (fileExists) {
174+
// Save current state for undo if file exists
175+
const currentContent = await fs.readFile(absolutePath, 'utf8');
176+
if (!fileStateHistory[absolutePath]) {
177+
fileStateHistory[absolutePath] = [];
178+
}
179+
fileStateHistory[absolutePath].push(currentContent);
180+
} else {
181+
// Initialize history for new files
182+
fileStateHistory[absolutePath] = [];
183+
}
184+
185+
// Create or overwrite the file
186+
await fs.writeFile(absolutePath, file_text, 'utf8');
182187

183188
return {
184189
success: true,
185-
message: `File created: ${filePath}`,
190+
message: fileExists
191+
? `File overwritten: ${filePath}`
192+
: `File created: ${filePath}`,
186193
};
187194
}
188195

0 commit comments

Comments
 (0)