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
25 changes: 19 additions & 6 deletions src/core/vscode-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ const DEFAULT_SETTINGS: Record<string, unknown> = {
*/
export type PathPlaceholderMap = Map<string, string>;

function normalizeWorkspacePath(path: string): string {
return path.replace(/\\/g, '/');
}

function resolveFolderAbsolutePath(workspacePath: string, folderPath: string): string {
return (isAbsolute(folderPath)
? folderPath
: resolve(workspacePath, folderPath)
).replace(/\\/g, '/');
}

function resolveFolderDisplayPath(folderPath: string): string {
return normalizeWorkspacePath(folderPath);
}

/**
* Build a placeholder map from repositories using path as the lookup key.
*
Expand Down Expand Up @@ -127,8 +142,8 @@ export function generateVscodeWorkspace(

// 1. Repository folders (from workspace.yaml)
for (const repo of repositories) {
const absolutePath = resolve(workspacePath, repo.path).replace(/\\/g, '/');
const entry: WorkspaceFolder = { path: absolutePath };
const absolutePath = resolveFolderAbsolutePath(workspacePath, repo.path);
const entry: WorkspaceFolder = { path: resolveFolderDisplayPath(repo.path) };
if (repo.name) entry.name = repo.name;
folders.push(entry);
seenPaths.add(absolutePath);
Expand All @@ -138,11 +153,9 @@ export function generateVscodeWorkspace(
if (resolvedTemplate && Array.isArray(resolvedTemplate.folders)) {
for (const folder of resolvedTemplate.folders as WorkspaceFolder[]) {
const rawPath = folder.path as string;
const normalizedPath = (typeof rawPath === 'string' && !isAbsolute(rawPath)
? resolve(workspacePath, rawPath)
: rawPath).replace(/\\/g, '/');
const normalizedPath = resolveFolderAbsolutePath(workspacePath, rawPath);
if (!seenPaths.has(normalizedPath)) {
const entry: WorkspaceFolder = { path: normalizedPath };
const entry: WorkspaceFolder = { path: resolveFolderDisplayPath(rawPath) };
if (folder.name) entry.name = folder.name;
folders.push(entry);
seenPaths.add(normalizedPath);
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/vscode-workspace-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ clients:
const content = JSON.parse(readFileSync(expectedPath, 'utf-8'));
expect(content.folders).toHaveLength(2);
expect(content.folders[0].path).toBe('.');
expect(content.folders[1].path).toBe('../myrepo');
expect(content.settings).toEqual({ 'chat.agent.maxRequests': 999 });
});

Expand Down
9 changes: 4 additions & 5 deletions tests/unit/cli/workspace-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ clients:

const folders = result.folders as Array<{ path: string }>;
expect(folders[0].path).toBe('.');
// On Windows paths are absolute (C:\...) not starting with /
// Just verify they are not relative (don't start with . or ..)
for (const folder of folders.slice(1)) {
expect(folder.path.startsWith('.')).toBe(false);
}
expect(folders.slice(1)).toEqual([
{ path: '../backend' },
{ path: '../frontend' },
]);

expect(result.settings).toEqual({ 'chat.agent.maxRequests': 999 });
});
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/core/vscode-workspace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
const testBase = join(tmpdir(), 'allagents-test');

describe('generateVscodeWorkspace', () => {
test('generates workspace with repository folders resolved to absolute paths', () => {
test('generates workspace with repository folders preserving relative paths from workspace.yaml', () => {
const workspacePath = join(testBase, 'myapp');
const result = generateVscodeWorkspace({
workspacePath,
Expand All @@ -27,8 +27,8 @@ describe('generateVscodeWorkspace', () => {

expect(result.folders).toEqual([
{ path: '.' },
{ path: resolve(workspacePath, '../backend').replace(/\\/g, '/') },
{ path: resolve(workspacePath, '../frontend').replace(/\\/g, '/') },
{ path: '../backend' },
{ path: '../frontend' },
]);
});

Expand All @@ -45,8 +45,8 @@ describe('generateVscodeWorkspace', () => {

expect(result.folders).toEqual([
{ path: '.' },
{ path: resolve(workspacePath, '../backend').replace(/\\/g, '/'), name: 'API Server' },
{ path: resolve(workspacePath, '../frontend').replace(/\\/g, '/') },
{ path: '../backend', name: 'API Server' },
{ path: '../frontend' },
]);
});

Expand Down Expand Up @@ -85,8 +85,8 @@ describe('generateVscodeWorkspace', () => {
// extra is not a duplicate, so it's kept with its name
expect(result.folders).toEqual([
{ path: '.' },
{ path: resolve(workspacePath, '../backend').replace(/\\/g, '/') },
{ path: sharedPath },
{ path: '../backend' },
{ path: '../shared' },
{ path: extraPath, name: 'ExtraLib' },
]);
});
Expand Down