Skip to content

Commit 4c05663

Browse files
committed
fix(chat): Add more fsWrite validation and validate before diff view
1 parent 28168cb commit 4c05663

File tree

3 files changed

+31
-53
lines changed

3 files changed

+31
-53
lines changed

packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ export class Messenger {
331331
explanation = input.explanation
332332
}
333333
session.setShowDiffOnFileWrite(true)
334+
// validate the fsWrite tool input before showing the diff view
335+
await tool.tool.validate()
334336
changeList = await tool.tool.getDiffChanges()
335337
}
336338
if (tool.type === ToolType.FsRead) {

packages/core/src/codewhispererChat/tools/fsWrite.ts

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ interface BaseParams {
1717

1818
export interface CreateParams extends BaseParams {
1919
command: 'create'
20-
fileText?: string
21-
newStr?: string
20+
fileText: string
2221
}
2322

2423
export interface StrReplaceParams extends BaseParams {
@@ -118,24 +117,42 @@ export class FsWrite {
118117
}
119118

120119
public async validate(): Promise<void> {
120+
if (!this.params.path) {
121+
throw new Error('Path must not be empty')
122+
}
123+
const sanitizedPath = sanitizePath(this.params.path)
121124
switch (this.params.command) {
122-
case 'create':
123-
if (!this.params.path) {
124-
throw new Error('Path must not be empty')
125+
case 'create': {
126+
if (this.params.fileText === undefined) {
127+
throw new Error('fileText must be provided for create command')
128+
}
129+
const fileExists = await fs.existsFile(sanitizedPath)
130+
if (fileExists) {
131+
const oldContent = await fs.readFileText(sanitizedPath)
132+
if (oldContent === this.params.fileText) {
133+
throw new Error('The file already exists with the same content')
134+
}
125135
}
126136
break
127-
case 'strReplace':
137+
}
138+
case 'strReplace': {
139+
if (this.params.oldStr === this.params.newStr) {
140+
throw new Error('The provided oldStr and newStr are the exact same, this is a no-op')
141+
}
142+
const fileExists = await fs.existsFile(sanitizedPath)
143+
if (!fileExists) {
144+
throw new Error('The provided path must exist in order to replace contents into it')
145+
}
146+
break
147+
}
128148
case 'insert': {
129-
const fileExists = await fs.existsFile(this.params.path)
149+
const fileExists = await fs.existsFile(sanitizedPath)
130150
if (!fileExists) {
131-
throw new Error('The provided path must exist in order to replace or insert contents into it')
151+
throw new Error('The provided path must exist in order to insert contents into it')
132152
}
133153
break
134154
}
135155
case 'append':
136-
if (!this.params.path) {
137-
throw new Error('Path must not be empty')
138-
}
139156
if (!this.params.newStr) {
140157
throw new Error('Content to append must not be empty')
141158
}
@@ -220,15 +237,7 @@ export class FsWrite {
220237
}
221238

222239
private getCreateCommandText(params: CreateParams): string {
223-
if (params.fileText) {
224-
return params.fileText
225-
}
226-
if (params.newStr) {
227-
this.logger.warn('Required field `fileText` is missing, use the provided `newStr` instead')
228-
return params.newStr
229-
}
230-
this.logger.warn('No content provided for the create command')
231-
return ''
240+
return params.fileText
232241
}
233242

234243
private escapeRegExp(string: string): string {

packages/core/src/test/codewhispererChat/tools/fsWrite.test.ts

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -66,39 +66,6 @@ describe('FsWrite Tool', function () {
6666

6767
assert.deepStrictEqual(output, expectedOutput)
6868
})
69-
70-
it('uses newStr when fileText is not provided', async function () {
71-
const filePath = path.join(testFolder.path, 'file2.txt')
72-
73-
const params: CreateParams = {
74-
command: 'create',
75-
newStr: 'Hello World',
76-
path: filePath,
77-
}
78-
const fsWrite = new FsWrite(params)
79-
const output = await fsWrite.invoke(process.stdout)
80-
81-
const content = await fs.readFileText(filePath)
82-
assert.strictEqual(content, 'Hello World')
83-
84-
assert.deepStrictEqual(output, expectedOutput)
85-
})
86-
87-
it('creates an empty file when no content is provided', async function () {
88-
const filePath = path.join(testFolder.path, 'file3.txt')
89-
90-
const params: CreateParams = {
91-
command: 'create',
92-
path: filePath,
93-
}
94-
const fsWrite = new FsWrite(params)
95-
const output = await fsWrite.invoke(process.stdout)
96-
97-
const content = await fs.readFileText(filePath)
98-
assert.strictEqual(content, '')
99-
100-
assert.deepStrictEqual(output, expectedOutput)
101-
})
10269
})
10370

10471
describe('handleStrReplace', async function () {

0 commit comments

Comments
 (0)