Skip to content

Commit 1e0e01b

Browse files
authored
feat: add append_to_file tool for appending content to files (#2712)
- Implemented the append_to_file tool to allow users to append content to existing files or create new ones if they do not exist. - Updated the rules and instructions to include the new tool. - Added tests for the append_to_file functionality, covering various scenarios including error handling and content preprocessing. - Enhanced the experiment schema to include the new append_to_file experiment ID. - Updated relevant interfaces and types to accommodate the new tool. - Modified the UI to display the append_to_file tool in the appropriate sections.
1 parent d3c37ea commit 1e0e01b

File tree

14 files changed

+874
-2
lines changed

14 files changed

+874
-2
lines changed

src/core/Cline.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ import { askFollowupQuestionTool } from "./tools/askFollowupQuestionTool"
7676
import { switchModeTool } from "./tools/switchModeTool"
7777
import { attemptCompletionTool } from "./tools/attemptCompletionTool"
7878
import { newTaskTool } from "./tools/newTaskTool"
79+
import { appendToFileTool } from "./tools/appendToFileTool"
7980

8081
export type ToolResponse = string | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam>
8182
type UserContent = Array<Anthropic.Messages.ContentBlockParam>
@@ -1390,6 +1391,8 @@ export class Cline extends EventEmitter<ClineEvents> {
13901391
return `[${block.name} for '${block.params.task}']`
13911392
case "write_to_file":
13921393
return `[${block.name} for '${block.params.path}']`
1394+
case "append_to_file":
1395+
return `[${block.name} for '${block.params.path}']`
13931396
case "apply_diff":
13941397
return `[${block.name} for '${block.params.path}']`
13951398
case "search_files":
@@ -1573,6 +1576,9 @@ export class Cline extends EventEmitter<ClineEvents> {
15731576
case "write_to_file":
15741577
await writeToFileTool(this, block, askApproval, handleError, pushToolResult, removeClosingTag)
15751578
break
1579+
case "append_to_file":
1580+
await appendToFileTool(this, block, askApproval, handleError, pushToolResult, removeClosingTag)
1581+
break
15761582
case "apply_diff":
15771583
await applyDiffTool(this, block, askApproval, handleError, pushToolResult, removeClosingTag)
15781584
break

src/core/assistant-message/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const toolUseNames = [
1212
"execute_command",
1313
"read_file",
1414
"write_to_file",
15+
"append_to_file",
1516
"apply_diff",
1617
"insert_content",
1718
"search_and_replace",
@@ -94,6 +95,11 @@ export interface WriteToFileToolUse extends ToolUse {
9495
params: Partial<Pick<Record<ToolParamName, string>, "path" | "content" | "line_count">>
9596
}
9697

98+
export interface AppendToFileToolUse extends ToolUse {
99+
name: "append_to_file"
100+
params: Partial<Pick<Record<ToolParamName, string>, "path" | "content">>
101+
}
102+
97103
export interface InsertCodeBlockToolUse extends ToolUse {
98104
name: "insert_content"
99105
params: Partial<Pick<Record<ToolParamName, string>, "path" | "operations">>

src/core/prompts/__tests__/__snapshots__/system.test.ts.snap

Lines changed: 308 additions & 0 deletions
Large diffs are not rendered by default.

src/core/prompts/sections/rules.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ function getEditingInstructions(diffStrategy?: DiffStrategy, experiments?: Recor
1616
if (experiments?.["insert_content"]) {
1717
availableTools.push("insert_content (for adding lines to existing files)")
1818
}
19+
if (experiments?.["append_to_file"]) {
20+
availableTools.push("append_to_file (for appending content to the end of files)")
21+
}
1922
if (experiments?.["search_and_replace"]) {
2023
availableTools.push("search_and_replace (for finding and replacing individual pieces of text)")
2124
}
@@ -32,6 +35,12 @@ function getEditingInstructions(diffStrategy?: DiffStrategy, experiments?: Recor
3235
)
3336
}
3437

38+
if (experiments?.["append_to_file"]) {
39+
instructions.push(
40+
"- The append_to_file tool adds content to the end of files, such as appending new log entries or adding new data records. This tool will always add the content at the end of the file.",
41+
)
42+
}
43+
3544
if (experiments?.["search_and_replace"]) {
3645
instructions.push(
3746
"- The search_and_replace tool finds and replaces text or regex in files. This tool allows you to search for a specific regex pattern or text and replace it with another value. Be cautious when using this tool to ensure you are replacing the correct text. It can support multiple operations at once.",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ToolArgs } from "./types"
2+
3+
export function getAppendToFileDescription(args: ToolArgs): string {
4+
return `## append_to_file
5+
Description: Request to append content to a file at the specified path. If the file exists, the content will be appended to the end of the file. If the file doesn't exist, it will be created with the provided content. This tool will automatically create any directories needed to write the file.
6+
Parameters:
7+
- path: (required) The path of the file to append to (relative to the current workspace directory ${args.cwd})
8+
- content: (required) The content to append to the file. The content will be added at the end of the existing file content. Do NOT include line numbers in the content.
9+
Usage:
10+
<append_to_file>
11+
<path>File path here</path>
12+
<content>
13+
Your content to append here
14+
</content>
15+
</append_to_file>
16+
17+
Example: Requesting to append to a log file
18+
<append_to_file>
19+
<path>logs/app.log</path>
20+
<content>
21+
[2024-04-17 15:20:30] New log entry
22+
[2024-04-17 15:20:31] Another log entry
23+
</content>
24+
</append_to_file>`
25+
}

src/core/prompts/tools/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { getExecuteCommandDescription } from "./execute-command"
22
import { getReadFileDescription } from "./read-file"
33
import { getFetchInstructionsDescription } from "./fetch-instructions"
44
import { getWriteToFileDescription } from "./write-to-file"
5+
import { getAppendToFileDescription } from "./append-to-file"
56
import { getSearchFilesDescription } from "./search-files"
67
import { getListFilesDescription } from "./list-files"
78
import { getInsertContentDescription } from "./insert-content"
@@ -26,6 +27,7 @@ const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined>
2627
read_file: (args) => getReadFileDescription(args),
2728
fetch_instructions: () => getFetchInstructionsDescription(),
2829
write_to_file: (args) => getWriteToFileDescription(args),
30+
append_to_file: (args) => getAppendToFileDescription(args),
2931
search_files: (args) => getSearchFilesDescription(args),
3032
list_files: (args) => getListFilesDescription(args),
3133
list_code_definition_names: (args) => getListCodeDefinitionNamesDescription(args),
@@ -101,6 +103,7 @@ export {
101103
getReadFileDescription,
102104
getFetchInstructionsDescription,
103105
getWriteToFileDescription,
106+
getAppendToFileDescription,
104107
getSearchFilesDescription,
105108
getListFilesDescription,
106109
getListCodeDefinitionNamesDescription,

0 commit comments

Comments
 (0)