Skip to content

Commit 6292539

Browse files
committed
refactor(tools): Make applyDiffTool backward compatible and fix errors
Makes `src/core/tools/applyDiffTool.ts` backward compatible by allowing it to process both the new XML-based `args` parameter and the legacy `path`, `diff`, and `start_line` parameters. This change also resolves TypeScript errors that arose from duplicated code during the initial refactoring for multi-diff support.
1 parent e271246 commit 6292539

File tree

1 file changed

+62
-36
lines changed

1 file changed

+62
-36
lines changed

src/core/tools/applyDiffTool.ts

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ export async function applyDiffTool(
3030
removeClosingTag: RemoveClosingTag,
3131
) {
3232
const argsXmlTag: string | undefined = block.params.args
33+
const legacyPath: string | undefined = block.params.path
34+
const legacyDiffContent: string | undefined = block.params.diff
35+
const legacyStartLineStr: string | undefined = block.params.start_line
36+
3337
let operationsMap: Record<string, DiffOperation> = {}
38+
let usingLegacyParams = false
3439

3540
// Handle partial message first
3641
if (block.partial) {
@@ -40,6 +45,9 @@ export async function applyDiffTool(
4045
if (match) {
4146
filePath = match[1]
4247
}
48+
} else if (legacyPath) {
49+
// Use legacy path if argsXmlTag is not present for partial messages
50+
filePath = legacyPath
4351
}
4452

4553
const sharedMessageProps: ClineSayTool = {
@@ -51,51 +59,67 @@ export async function applyDiffTool(
5159
return
5260
}
5361

54-
if (!argsXmlTag) {
55-
cline.consecutiveMistakeCount++
56-
cline.recordToolError("apply_diff")
57-
const errorMsg = await cline.sayAndCreateMissingParamError("apply_diff", "args")
58-
pushToolResult(errorMsg)
59-
return
60-
}
61-
62-
// Parse file entries from XML
63-
try {
64-
const parsed = parseXml(argsXmlTag, ["file.diff.content"]) as any
65-
const files = Array.isArray(parsed.file) ? parsed.file : [parsed.file].filter(Boolean)
62+
if (argsXmlTag) {
63+
// Parse file entries from XML (new way)
64+
try {
65+
const parsed = parseXml(argsXmlTag, ["file.diff.content"]) as any
66+
const files = Array.isArray(parsed.file) ? parsed.file : [parsed.file].filter(Boolean)
6667

67-
for (const file of files) {
68-
if (!file.path || !file.diff) continue
68+
for (const file of files) {
69+
if (!file.path || !file.diff) continue
6970

70-
const filePath = file.path
71+
const filePath = file.path
7172

72-
// Initialize the operation in the map if it doesn't exist
73-
if (!operationsMap[filePath]) {
74-
operationsMap[filePath] = {
75-
path: filePath,
76-
diff: [],
73+
// Initialize the operation in the map if it doesn't exist
74+
if (!operationsMap[filePath]) {
75+
operationsMap[filePath] = {
76+
path: filePath,
77+
diff: [],
78+
}
7779
}
78-
}
7980

80-
// Handle diff as either array or single element
81-
const diffs = Array.isArray(file.diff) ? file.diff : [file.diff]
81+
// Handle diff as either array or single element
82+
const diffs = Array.isArray(file.diff) ? file.diff : [file.diff]
8283

83-
for (let i = 0; i < diffs.length; i++) {
84-
const diff = diffs[i]
85-
let diffContent: string
86-
let startLine: number | undefined
84+
for (let i = 0; i < diffs.length; i++) {
85+
const diff = diffs[i]
86+
let diffContent: string
87+
let startLine: number | undefined
8788

88-
diffContent = diff.content
89-
startLine = diff.start_line ? parseInt(diff.start_line) : undefined
89+
diffContent = diff.content
90+
startLine = diff.start_line ? parseInt(diff.start_line) : undefined
9091

91-
operationsMap[filePath].diff.push({
92-
content: diffContent,
93-
startLine,
94-
})
92+
operationsMap[filePath].diff.push({
93+
content: diffContent,
94+
startLine,
95+
})
96+
}
9597
}
98+
} catch (error) {
99+
throw new Error(`Failed to parse apply_diff XML: ${error instanceof Error ? error.message : String(error)}`)
96100
}
97-
} catch (error) {
98-
throw new Error(`Failed to parse apply_diff XML: ${error instanceof Error ? error.message : String(error)}`)
101+
} else if (legacyPath && typeof legacyDiffContent === "string") {
102+
// Handle legacy parameters (old way)
103+
usingLegacyParams = true
104+
operationsMap[legacyPath] = {
105+
path: legacyPath,
106+
diff: [
107+
{
108+
content: legacyDiffContent, // Unescaping will be handled later like new diffs
109+
startLine: legacyStartLineStr ? parseInt(legacyStartLineStr) : undefined,
110+
},
111+
],
112+
}
113+
} else {
114+
// Neither new XML args nor old path/diff params are sufficient
115+
cline.consecutiveMistakeCount++
116+
cline.recordToolError("apply_diff")
117+
const errorMsg = await cline.sayAndCreateMissingParamError(
118+
"apply_diff",
119+
"args (or legacy 'path' and 'diff' parameters)",
120+
)
121+
pushToolResult(errorMsg)
122+
return
99123
}
100124

101125
// If no operations were extracted, bail out
@@ -105,7 +129,9 @@ export async function applyDiffTool(
105129
pushToolResult(
106130
await cline.sayAndCreateMissingParamError(
107131
"apply_diff",
108-
"args (must contain at least one valid file element)",
132+
usingLegacyParams
133+
? "legacy 'path' and 'diff' (must be valid and non-empty)"
134+
: "args (must contain at least one valid file element)",
109135
),
110136
)
111137
return

0 commit comments

Comments
 (0)