diff --git a/src/features/tmux-installer/main/infrastructure/wsl/TmuxWslService.ts b/src/features/tmux-installer/main/infrastructure/wsl/TmuxWslService.ts index b6ccfcda..a56ebea8 100644 --- a/src/features/tmux-installer/main/infrastructure/wsl/TmuxWslService.ts +++ b/src/features/tmux-installer/main/infrastructure/wsl/TmuxWslService.ts @@ -115,11 +115,14 @@ export class TmuxWslService { }; } - const distros = this.#parseWslDistros(distroListProbe.stdout); + const listedDistros = this.#parseWslDistros(distroListProbe.stdout); + const serviceDistros = listedDistros.filter((distro) => this.#isInternalWslDistro(distro)); + const distros = listedDistros.filter((distro) => !this.#isInternalWslDistro(distro)); if (distros.length === 0) { if (persistedPreferredDistro) { await this.#preferenceStore.clearPreferredDistro(); } + const hasOnlyServiceDistros = serviceDistros.length > 0; return { preference: null, status: { @@ -134,7 +137,9 @@ export class TmuxWslService { tmuxBinaryPath: null, statusDetail: rebootRequired ? 'WSL was installed, but Windows still needs a restart before a Linux distro can be configured.' - : 'WSL is available, but no Linux distribution is installed yet.', + : hasOnlyServiceDistros + ? `WSL has only service distributions (${serviceDistros.join(', ')}). Install a Linux distribution such as Ubuntu for teammate runtime support.` + : 'WSL is available, but no Linux distribution is installed yet.', }, }; } @@ -420,7 +425,6 @@ export class TmuxWslService { .split(/\r?\n/) .map((line) => line.replace(/\0/g, '').trim()) .map((line) => line.replace(/^\*\s*/, '').trim()) - .filter((line) => !this.#isInternalWslDistro(line)) .filter(Boolean); } diff --git a/src/features/tmux-installer/main/infrastructure/wsl/__tests__/TmuxWslService.test.ts b/src/features/tmux-installer/main/infrastructure/wsl/__tests__/TmuxWslService.test.ts index c65aa4a7..4b8f8ab1 100644 --- a/src/features/tmux-installer/main/infrastructure/wsl/__tests__/TmuxWslService.test.ts +++ b/src/features/tmux-installer/main/infrastructure/wsl/__tests__/TmuxWslService.test.ts @@ -162,7 +162,8 @@ describe('TmuxWslService', () => { expect(result.status.wslInstalled).toBe(true); expect(result.status.distroName).toBeNull(); - expect(result.status.statusDetail).toContain('no Linux distribution'); + expect(result.status.statusDetail).toContain('only service distributions'); + expect(result.status.statusDetail).toContain('docker-desktop'); }); it('switches preference source away from persisted after clearing a stale distro', async () => { diff --git a/src/main/services/discovery/ProjectPathResolver.ts b/src/main/services/discovery/ProjectPathResolver.ts index 161b56ba..a8376dc9 100644 --- a/src/main/services/discovery/ProjectPathResolver.ts +++ b/src/main/services/discovery/ProjectPathResolver.ts @@ -32,6 +32,11 @@ interface ResolveProjectPathOptions { forceRefresh?: boolean; } +function isAbsolutePathLike(value: string): boolean { + const slashPath = value.replace(/\\/g, '/'); + return path.isAbsolute(value) || /^[a-zA-Z]:\//.test(slashPath) || slashPath.startsWith('//'); +} + export class ProjectPathResolver { private readonly projectsDir: string; private readonly fsProvider: FileSystemProvider; @@ -66,7 +71,7 @@ export class ProjectPathResolver { } const cwdHint = opts.cwdHint?.trim(); - if (cwdHint && path.isAbsolute(cwdHint)) { + if (cwdHint && isAbsolutePathLike(cwdHint)) { this.projectPathCache.set(projectId, cwdHint); return cwdHint; } @@ -85,7 +90,7 @@ export class ProjectPathResolver { for (const sessionPath of sessionPaths.slice(0, maxPathsToInspect)) { try { const cwd = await extractCwd(sessionPath, this.fsProvider); - if (cwd && path.isAbsolute(cwd)) { + if (cwd && isAbsolutePathLike(cwd)) { this.projectPathCache.set(projectId, cwd); return cwd; }