fix: handle Windows drive-letter paths across the codebase (#148)
* Add metrics collection and terminal performance tests
* fix: handle Windows drive-letter paths across the codebase
Windows paths like C:\Users\foo\project were broken in multiple places:
- agent-storage slugified D:\MyProject as D:-MyProject (illegal colon)
- terminal-manager rejected all non-/ paths as relative
- bootstrap parser misparsed drive colons as TCP host:port
- daemon/client connection helpers misclassified Windows paths
- CLI cwd filtering used hardcoded / separators
- checkout-git worktree detection used hardcoded / in path checks
- worktree archive used split("/").pop() instead of path.basename()
All path helpers now normalize separators and handle Windows
drive letters with case-insensitive comparison where needed.
This commit is contained in:
@@ -45,10 +45,15 @@ export function normalizeDaemonHost(raw: string): string | null {
|
||||
return trimmed.startsWith("\\\\.\\pipe\\") ? `pipe://${trimmed}` : trimmed;
|
||||
}
|
||||
|
||||
if (path.isAbsolute(trimmed)) {
|
||||
if (trimmed.startsWith("/") || trimmed.startsWith("~")) {
|
||||
return `unix://${trimmed}`;
|
||||
}
|
||||
|
||||
// Windows absolute paths (e.g. C:\Users\foo) are filesystem paths, not TCP or IPC targets.
|
||||
if (/^[A-Za-z]:[/\\]/.test(trimmed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (/^\d+$/.test(trimmed)) {
|
||||
return `127.0.0.1:${trimmed}`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Path utilities for cwd filtering in agent commands.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if `candidatePath` is the same directory as `basePath` or a descendant of it.
|
||||
*
|
||||
* Handles both Unix (/) and Windows (\) path separators, including mixed separators.
|
||||
* This is important because agent cwd paths come from the agent's OS (could be Windows)
|
||||
* while the CLI filter path comes from the user (could also be Windows or Unix).
|
||||
*/
|
||||
export function isSameOrDescendantPath(basePath: string, candidatePath: string): boolean {
|
||||
// Normalize both paths: replace all backslashes with forward slashes, strip trailing separator
|
||||
let normalizedBase = basePath.replace(/\\/g, "/").replace(/\/$/, "");
|
||||
let normalizedCandidate = candidatePath.replace(/\\/g, "/").replace(/\/$/, "");
|
||||
|
||||
// Windows paths are case-insensitive — detect by drive letter prefix (e.g. "C:/")
|
||||
if (/^[a-zA-Z]:\//.test(normalizedBase) || /^[a-zA-Z]:\//.test(normalizedCandidate)) {
|
||||
normalizedBase = normalizedBase.toLowerCase();
|
||||
normalizedCandidate = normalizedCandidate.toLowerCase();
|
||||
}
|
||||
|
||||
return (
|
||||
normalizedCandidate === normalizedBase ||
|
||||
normalizedCandidate.startsWith(normalizedBase + "/")
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user