Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions src/web/chat/utils/tool-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
* Convert absolute path to relative path if it's a subpath of working directory
*/
export function formatFilePath(path: string, workingDirectory?: string): string {

if (!path) {
return path;
}

// If we have a working directory and the path starts with it, make it relative
if (workingDirectory && path.startsWith(workingDirectory)) {
const relativePath = path.slice(workingDirectory.length);
// Remove leading slash if present
const cleaned = relativePath.startsWith('/') ? relativePath.slice(1) : relativePath;
const result = cleaned ? `./${cleaned}` : './';
return result;

if (workingDirectory) {
const normalizedWorkingDir = workingDirectory.replace(/[\\/]+$/, '');
const comparisonPath = path.replace(/[\\/]+$/, '');

const isSamePath = comparisonPath === normalizedWorkingDir;
const isSubPath = comparisonPath.startsWith(`${normalizedWorkingDir}/`) || comparisonPath.startsWith(`${normalizedWorkingDir}\\`);

if (isSamePath || isSubPath) {
const relativePath = path.slice(normalizedWorkingDir.length).replace(/^[\\/]+/, '');
return relativePath ? `./${relativePath}` : './';
}
}

// If it starts with user home directory, show as ~
Expand Down Expand Up @@ -126,4 +129,4 @@ export function extractDomain(url: string): string {
} catch (e) {
return url;
}
}
}
20 changes: 20 additions & 0 deletions tests/unit/web/utils/tool-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { formatFilePath } from '@/web/chat/utils/tool-utils';

describe('formatFilePath', () => {
it('returns relative path when inside working directory', () => {
expect(formatFilePath('/home/user/project/src/index.ts', '/home/user/project'))
.toBe('./src/index.ts');
});

it('does not collapse sibling directories that only share a prefix', () => {
expect(formatFilePath('/home/user/project-other/file.ts', '/home/user/project'))
.toBe('~/user/project-other/file.ts');
});

it('handles windows-style paths with trailing slashes', () => {
expect(formatFilePath('C:/workspace/app/src/main.ts', 'C:/workspace/app/'))
.toBe('./src/main.ts');
expect(formatFilePath('C:/workspace/app-logs/output.log', 'C:/workspace/app/'))
.toBe('C:/workspace/app-logs/output.log');
});
});