경로
AbstractPath
섹션 제목: “AbstractPath”ActiveCli.Path.AbstractPath — 파일시스템 위치를, 어떤 구체적인 종류의 경로로서.
abstract class AbstractPath { toString(): string; abstract toWslPath(): string; abstract isSpawnableAsCwd(): boolean;}경로는 우리 경계에 맨 문자열로 도착합니다 — 호출자의 옵션에서, 프로젝트 루트를 건네는 IDE에서, CLI의 JSON 출력에서. 문자열은 “너는 Windows 드라이브 경로냐 Linux 경로냐”에 답할 수 없으므로, 그것을 알아야 하는 모든 호출자가 각자 다시 도출하고, 그 도출들은 서로 어긋납니다. 여기서는 클래스가 곧 답입니다.
| 멤버 | 설명 |
|---|---|
toString() |
주어진 그대로의 경로. 구분자까지 포함해서. |
toWslPath() |
WSL 배포판 안에서 도는 프로세스가 보게 될 경로로서의 이 위치. 출발지가 아니라 목적지를 기준으로 이름 붙인 것은, 호출자가 고르는 것이 그것이기 때문입니다: “Linux 자식을 위해 자신을 렌더링하라”. 이미 그 세계에 속한 경로는 자기 자신으로 답합니다. |
isSpawnableAsCwd() |
현재 호스트에서 이 경로를 cwd로 삼아 자식을 spawn하는 것이 안전한지 여부. |
PathParser
섹션 제목: “PathParser”ActiveCli.Path.PathParser — 경로 문자열을 그것이 실제로 속한 종류로 바꿉니다. 맨 문자열이 더 이상 여행하도록 허용되지 않는 경계입니다. 경로가 도착하는 순간 이것을 호출하고, 그 뒤로는 인스턴스를 전달하십시오.
class PathParser { parse(raw: string): AbstractPath;}| 입력 | 결과 | toWslPath() |
|---|---|---|
//wsl.localhost/Ubuntu/home/user/proj |
WslUncPath |
/home/user/proj |
/home/user/proj |
PosixPath |
/home/user/proj |
C:\Users\foo |
WindowsPath |
/mnt/c/Users/foo |
src\core (상대 경로) |
PosixPath |
src/core |
어떤 종류로도 절대 경로가 아닌 것은 POSIX로 취급되며, 나가는 길에 구분자를 정규화하고 spawn 가능한 상태로 남습니다 — 상대 cwd에 대한 정직한 답입니다.
PathParser가 AbstractPath의 static이 아니라 별도 클래스인 것은, 베이스가 자신의 하위 클래스를 import하지 않아도 되게 하기 위함입니다.
PosixPath
섹션 제목: “PosixPath”ActiveCli.Path.PosixPath — Linux/macOS 경로(/home/user/proj), 그리고 다른 종류의 절대 경로가 아닌 모든 것에 대한 폴백.
class PosixPath extends AbstractPath { constructor(raw: string); toWslPath(): string; // 구분자 정규화 isSpawnableAsCwd(): boolean; // 언제나 true}이미 POSIX 자식에게 네이티브이므로 spawn cwd로 언제나 안전합니다. 상대 경로는 여전히 역슬래시(src\core)를 달고 올 수 있으며, 구분자는 생성 시점이 아니라 toWslPath()에서 변환됩니다 — 그래야 toString()이 우리가 받은 것에 대해 정직하게 남습니다.
WindowsPath
섹션 제목: “WindowsPath”ActiveCli.Path.WindowsPath — Windows 드라이브 경로(C:\Users\foo, 또는 구분자가 없는 C:Users\foo).
class WindowsPath extends AbstractPath { constructor(raw: string); static matches(raw: string): boolean; // 두 번째 문자가 ':' toWslPath(): string; isSpawnableAsCwd(): boolean; // 언제나 true}WSL 배포판 안에서 Windows 드라이브는 /mnt/<letter> 아래에 마운트되므로, Linux 자식에게 건네야 하는 것은 그 형태입니다.
parser.parse('D:\\Projects').toWslPath(); // '/mnt/d/Projects'parser.parse('C:\\').toWslPath(); // '/mnt/c' — '/mnt/c/'가 아님parser.parse('C:Users\\foo').toWslPath(); // '/mnt/c/Users/foo'드라이브 문자를 소문자로 바꾸는 것은 마운트 지점이 /mnt/C가 아니라 /mnt/c이기 때문입니다. 끝의 슬래시를 떼는 것은 /mnt/c/가 마운트 지점 자체와 다른 위치로 읽히기 때문입니다.
WslUncPath
섹션 제목: “WslUncPath”ActiveCli.Path.WslUncPath — WSL UNC 경로: \\wsl.localhost\Ubuntu\home\user\proj, 또는 구형인 \\wsl$\NixOS\home\maicol07.
class WslUncPath extends AbstractPath { static matches(raw: string): boolean; static parse(raw: string): WslUncPath | null;
readonly distro: string; readonly linuxPath: string;
toWslPath(): string; // 안쪽의 Linux 경로 isSpawnableAsCwd(): boolean; // 언제나 false}이것이 양쪽 모두에서 spawn을 깨뜨리는 경로입니다. 그래서 isSpawnableAsCwd()는 언제나 false입니다. cmd.exe는 UNC cwd를 아예 거부하고, 배포판 안에서 도는 프로세스에는 그런 위치가 존재하지 않습니다.
WslUncPath.parse('\\\\wsl.localhost\\Ubuntu\\home\\user\\proj');// distro 'Ubuntu', linuxPath '/home/user/proj'
WslUncPath.parse('\\\\wsl$\\NixOS\\home\\maicol07');// distro 'NixOS', linuxPath '/home/maicol07'
WslUncPath.parse('\\\\wsl.localhost\\Ubuntu');// distro 'Ubuntu', linuxPath '/'
WslUncPath.parse('\\\\server\\share\\file'); // null — UNC 경로이지만 WSL의 것은 아님WslUncPath.parse('/home/user'); // nulldistro id는 원래의 대소문자를 유지합니다. wsl -d가 그에 대해 대소문자를 가리기 때문입니다. \\wsl.localhost\ / \\wsl$\ 호스트 접두사만 대소문자 구분 없이 매칭됩니다.
슬래시로 된 입력도 일치로 칩니다. //wsl.localhost/Ubuntu/...는 IDE가 백엔드에 건네는 바로 그 형태이며, 슬래시로 시작한다는 이유만으로 POSIX 경로로 오인되어서는 안 됩니다.
이것이 spawn 시점에 중요해지는 지점
섹션 제목: “이것이 spawn 시점에 중요해지는 지점”SpawnOptions는 workingDirectory를 들어오는 길에 변환합니다 — 문자열을, 자신이 spawn cwd가 될 수 있는지를 아는 무언가로 바꾸기에 가장 짧은 자리입니다.
const options = new SpawnOptions({ workingDirectory: '//wsl.localhost/Ubuntu/home/me' });options.workingDirectory?.isSpawnableAsCwd(); // falseoptions.workingDirectory?.toWslPath(); // '/home/me'ClaudeAdapter는 spawn 불가능한 cwd를 넘기는 대신 아예 생략합니다. 그것을 넘기면 바이너리가 아니라 디렉토리를 지목하는 ENOENT로 spawn이 실패하기 때문입니다 — 프로세스 실행 실패를 보십시오.