Skip to content

Commit 33b2e0d

Browse files
authored
fix(serve): normalize Windows path separators in workspace file read responses (#4279)
`workspaceRelative` returned the platform-native separator from `path.relative`, leaking backslashes into `/file`, `/stat`, `/list`, and `/glob` response paths on Windows. Surfaced as a Windows-only CI failure in the `GET /glob > scopes glob matches to cwd` test (`['sub\\inside.ts']` vs expected `['sub/inside.ts']`). Always emit POSIX-style separators so SDK consumers see the same shape across platforms. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
1 parent b208f34 commit 33b2e0d

1 file changed

Lines changed: 7 additions & 1 deletion

File tree

packages/cli/src/serve/routes/workspaceFileRead.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,11 @@ async function handleGetGlob(
428428
* response payload. Missing `boundWorkspace` means the app was
429429
* misconfigured; never fall back to returning absolute filesystem
430430
* paths to clients.
431+
*
432+
* Always emits POSIX-style separators so SDK consumers see the same
433+
* shape regardless of the daemon's platform — `path.relative` on
434+
* Windows yields backslashes, which would otherwise leak into
435+
* `/file`, `/stat`, `/list`, and `/glob` response paths.
431436
*/
432437
function workspaceRelative(req: Request, resolved: string): string {
433438
const boundWorkspace = (req.app.locals as { boundWorkspace?: string })
@@ -436,7 +441,8 @@ function workspaceRelative(req: Request, resolved: string): string {
436441
throw new Error('bound workspace is not configured');
437442
}
438443
const rel = path.relative(boundWorkspace, resolved);
439-
return rel === '' ? '.' : rel;
444+
if (rel === '') return '.';
445+
return path.sep === '/' ? rel : rel.split(path.sep).join('/');
440446
}
441447

442448
export function registerWorkspaceFileReadRoutes(

0 commit comments

Comments
 (0)