mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 16:36:22 +02:00
added edit tool make precise edits
This commit is contained in:
parent
8029877792
commit
de6e9d85dd
3 changed files with 62 additions and 10 deletions
|
|
@ -88,12 +88,12 @@ When a user asks for ANY task that might require external capabilities (web sear
|
|||
## Workspace Access & Scope
|
||||
- You have full read/write access inside \`\${BASE_DIR}\` (this resolves to the user's \`~/.rowboat\` directory). Create folders, files, and agents there using builtin tools or allowed shell commands—don't wait for the user to do it manually.
|
||||
- If a user mentions a different root (e.g., \`~/.rowboatx\` or another path), clarify whether they meant the Rowboat workspace and propose the equivalent path you can act on. Only refuse if they explicitly insist on an inaccessible location.
|
||||
- Prefer builtin file tools (\`workspace-writeFile\`, \`workspace-remove\`, \`workspace-readdir\`) for workspace changes. Reserve refusal or "you do it" responses for cases that are truly outside the Rowboat sandbox.
|
||||
- Prefer builtin file tools (\`workspace-edit\` for modifications, \`workspace-writeFile\` for new files, \`workspace-remove\`, \`workspace-readdir\`) for workspace changes. Reserve refusal or "you do it" responses for cases that are truly outside the Rowboat sandbox.
|
||||
|
||||
## Builtin Tools vs Shell Commands
|
||||
|
||||
**IMPORTANT**: Rowboat provides builtin tools that are internal and do NOT require security allowlist entries:
|
||||
- \`workspace-readFile\`, \`workspace-writeFile\`, \`workspace-remove\` - File operations
|
||||
- \`workspace-readFile\`, \`workspace-writeFile\`, \`workspace-edit\`, \`workspace-remove\` - File operations
|
||||
- \`workspace-readdir\`, \`workspace-exists\`, \`workspace-stat\` - Directory exploration
|
||||
- \`workspace-mkdir\`, \`workspace-rename\`, \`workspace-copy\` - File/directory management
|
||||
- \`analyzeAgent\` - Agent analysis
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ The Rowboat copilot has access to special builtin tools that regular agents don'
|
|||
- \`workspace-readdir\` - List directory contents (supports recursive exploration)
|
||||
- \`workspace-readFile\` - Read file contents
|
||||
- \`workspace-writeFile\` - Create or update file contents
|
||||
- \`workspace-edit\` - Make precise edits by replacing specific text (safer than full rewrites)
|
||||
- \`workspace-remove\` - Remove files or directories
|
||||
- \`workspace-exists\` - Check if a file or directory exists
|
||||
- \`workspace-stat\` - Get file/directory statistics
|
||||
|
|
|
|||
|
|
@ -156,14 +156,14 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
mkdirp: z.boolean().optional().describe('Create parent directories if needed (default: true)'),
|
||||
expectedEtag: z.string().optional().describe('ETag to check for concurrent modifications (conflict detection)'),
|
||||
}),
|
||||
execute: async ({
|
||||
path: relPath,
|
||||
data,
|
||||
encoding,
|
||||
atomic,
|
||||
mkdirp,
|
||||
expectedEtag
|
||||
}: {
|
||||
execute: async ({
|
||||
path: relPath,
|
||||
data,
|
||||
encoding,
|
||||
atomic,
|
||||
mkdirp,
|
||||
expectedEtag
|
||||
}: {
|
||||
path: string;
|
||||
data: string;
|
||||
encoding?: 'utf8' | 'base64' | 'binary';
|
||||
|
|
@ -186,6 +186,57 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
},
|
||||
},
|
||||
|
||||
'workspace-edit': {
|
||||
description: 'Make precise edits to a file by replacing specific text. Safer than rewriting entire files - produces smaller diffs and reduces risk of data loss.',
|
||||
inputSchema: z.object({
|
||||
path: z.string().min(1).describe('Workspace-relative file path'),
|
||||
oldString: z.string().describe('Exact text to find and replace'),
|
||||
newString: z.string().describe('Replacement text'),
|
||||
replaceAll: z.boolean().optional().describe('Replace all occurrences (default: false, fails if not unique)'),
|
||||
}),
|
||||
execute: async ({
|
||||
path: relPath,
|
||||
oldString,
|
||||
newString,
|
||||
replaceAll = false
|
||||
}: {
|
||||
path: string;
|
||||
oldString: string;
|
||||
newString: string;
|
||||
replaceAll?: boolean;
|
||||
}) => {
|
||||
try {
|
||||
const result = await workspace.readFile(relPath, 'utf8');
|
||||
const content = result.data;
|
||||
|
||||
const occurrences = content.split(oldString).length - 1;
|
||||
|
||||
if (occurrences === 0) {
|
||||
return { error: 'oldString not found in file' };
|
||||
}
|
||||
|
||||
if (occurrences > 1 && !replaceAll) {
|
||||
return {
|
||||
error: `oldString found ${occurrences} times. Use replaceAll: true or provide more context to make it unique.`
|
||||
};
|
||||
}
|
||||
|
||||
const newContent = replaceAll
|
||||
? content.replaceAll(oldString, newString)
|
||||
: content.replace(oldString, newString);
|
||||
|
||||
await workspace.writeFile(relPath, newContent, { encoding: 'utf8' });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
replacements: replaceAll ? occurrences : 1
|
||||
};
|
||||
} catch (error) {
|
||||
return { error: error instanceof Error ? error.message : 'Unknown error' };
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
'workspace-mkdir': {
|
||||
description: 'Create a directory in the workspace',
|
||||
inputSchema: z.object({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue