Skip to content

Commit f0d6050

Browse files
authored
Merge branch 'feature/agentic-chat' into feature/agentic-chat
2 parents 3c8e737 + 3fb3d0b commit f0d6050

File tree

2 files changed

+124
-3
lines changed

2 files changed

+124
-3
lines changed

packages/core/src/shared/utilities/workspaceUtils.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -692,16 +692,15 @@ export function tryGetCurrentWorkingDirectory() {
692692
/**
693693
* Returns a one-character tag for a directory ('d'), symlink ('l'), or file ('-').
694694
*/
695-
695+
* Returns a one-character tag for a directory ('d'), symlink ('l'), or file ('-').
696+
*/
696697
export function formatListing(name: string, fileType: vscode.FileType, fullPath: string): string {
697698
let typeChar = '-'
698-
699699
if (fileType === vscode.FileType.Directory) {
700700
typeChar = 'd'
701701
} else if (fileType === vscode.FileType.SymbolicLink) {
702702
typeChar = 'l'
703703
}
704-
705704
return `${typeChar} ${fullPath}`
706705
}
707706

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import assert from 'assert'
6+
import { FsRead } from '../../../codewhispererChat/tools/fsRead'
7+
import { TestFolder } from '../../testUtil'
8+
import path from 'path'
9+
10+
describe('FsRead Tool', () => {
11+
let testFolder: TestFolder
12+
13+
before(async () => {
14+
testFolder = await TestFolder.create()
15+
})
16+
17+
it('throws if path is empty', async () => {
18+
const fsRead = new FsRead({ path: '' })
19+
await assert.rejects(fsRead.validate(), /Path cannot be empty/i, 'Expected an error about empty path')
20+
})
21+
22+
it('reads entire file', async () => {
23+
const fileContent = 'Line 1\nLine 2\nLine 3'
24+
const filePath = await testFolder.write('fullFile.txt', fileContent)
25+
26+
const fsRead = new FsRead({ path: filePath })
27+
await fsRead.validate()
28+
const result = await fsRead.invoke()
29+
30+
assert.strictEqual(result.output.kind, 'text', 'Output kind should be "text"')
31+
assert.strictEqual(result.output.content, fileContent, 'File content should match exactly')
32+
})
33+
34+
it('reads partial lines of a file', async () => {
35+
const fileContent = 'A\nB\nC\nD\nE\nF'
36+
const filePath = await testFolder.write('partialFile.txt', fileContent)
37+
38+
const fsRead = new FsRead({ path: filePath, readRange: [2, 4] })
39+
await fsRead.validate()
40+
const result = await fsRead.invoke()
41+
42+
assert.strictEqual(result.output.kind, 'text')
43+
assert.strictEqual(result.output.content, 'B\nC\nD')
44+
})
45+
46+
it('lists directory contents up to depth = 1', async () => {
47+
await testFolder.mkdir('subfolder')
48+
await testFolder.write('fileA.txt', 'fileA content')
49+
await testFolder.write(path.join('subfolder', 'fileB.md'), '# fileB')
50+
51+
const fsRead = new FsRead({ path: testFolder.path, readRange: [1] })
52+
await fsRead.validate()
53+
const result = await fsRead.invoke()
54+
55+
const lines = result.output.content.split('\n')
56+
const hasFileA = lines.some((line) => line.includes('- ') && line.includes('fileA.txt'))
57+
const hasSubfolder = lines.some((line) => line.includes('d ') && line.includes('subfolder'))
58+
59+
assert.ok(hasFileA, 'Should list fileA.txt in the directory output')
60+
assert.ok(hasSubfolder, 'Should list the subfolder in the directory output')
61+
})
62+
63+
it('throws error if path does not exist', async () => {
64+
const missingPath = path.join(testFolder.path, 'no_such_file.txt')
65+
const fsRead = new FsRead({ path: missingPath })
66+
67+
await assert.rejects(
68+
fsRead.validate(),
69+
/does not exist or cannot be accessed/i,
70+
'Expected an error indicating the path does not exist'
71+
)
72+
})
73+
74+
it('throws error if content exceeds 30KB', async function () {
75+
const bigContent = 'x'.repeat(35_000)
76+
const bigFilePath = await testFolder.write('bigFile.txt', bigContent)
77+
78+
const fsRead = new FsRead({ path: bigFilePath })
79+
await fsRead.validate()
80+
81+
await assert.rejects(
82+
fsRead.invoke(),
83+
/This tool only supports reading \d+ bytes at a time/i,
84+
'Expected a size-limit error'
85+
)
86+
})
87+
88+
it('invalid line range', async () => {
89+
const filePath = await testFolder.write('rangeTest.txt', '1\n2\n3')
90+
const fsRead = new FsRead({ path: filePath, readRange: [3, 2] })
91+
92+
await fsRead.validate()
93+
const result = await fsRead.invoke()
94+
assert.strictEqual(result.output.kind, 'text')
95+
assert.strictEqual(result.output.content, '')
96+
})
97+
98+
it('expands ~ path', async () => {
99+
const fsRead = new FsRead({ path: '~' })
100+
await fsRead.validate()
101+
const result = await fsRead.invoke()
102+
103+
assert.strictEqual(result.output.kind, 'text')
104+
assert.ok(result.output.content.length > 0)
105+
})
106+
107+
it('resolves relative path', async () => {
108+
await testFolder.mkdir('relTest')
109+
const filePath = path.join('relTest', 'relFile.txt')
110+
const content = 'Hello from a relative file!'
111+
await testFolder.write(filePath, content)
112+
113+
const relativePath = path.relative(process.cwd(), path.join(testFolder.path, filePath))
114+
115+
const fsRead = new FsRead({ path: relativePath })
116+
await fsRead.validate()
117+
const result = await fsRead.invoke()
118+
119+
assert.strictEqual(result.output.kind, 'text')
120+
assert.strictEqual(result.output.content, content)
121+
})
122+
})

0 commit comments

Comments
 (0)