From e485037c3446331d18d14107f9f3e2a2b64d510c Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Fri, 30 Oct 2026 11:40:08 +0800 Subject: [PATCH] fix(agents): resolve typed paths against Windows project roots --- src/features/agents/agents.test.ts | 2 ++ src/features/agents/composerModel.ts | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/features/agents/agents.test.ts b/src/features/agents/agents.test.ts index 5b269bc6..c6671741 100644 --- a/src/features/agents/agents.test.ts +++ b/src/features/agents/agents.test.ts @@ -288,5 +288,7 @@ describe("typed path references", () => { expect(resolveTyped("/r/idea", "../kalo/a.ts")).toBe("/r/kalo/a.ts"); expect(resolveTyped("/r/idea", "./src")).toBe("/r/idea/src"); expect(resolveTyped("/r/idea", "/etc/hosts")).toBe("/etc/hosts"); + expect(resolveTyped("C:\\r\\idea", "../kalo/a.ts")).toBe("C:/r/kalo/a.ts"); + expect(resolveTyped("C:\\r", "../../x")).toBe("C:/x"); }); }); diff --git a/src/features/agents/composerModel.ts b/src/features/agents/composerModel.ts index 66e0d7ed..c88f70dd 100644 --- a/src/features/agents/composerModel.ts +++ b/src/features/agents/composerModel.ts @@ -77,14 +77,19 @@ function inOrder(text: string, query: string): boolean { /** Whether an `@` query is a typed-out path (`../x`, `./x`, `/x`) rather than a project file search. */ export const isPathQuery = (query: string) => /^(\.\.?(\/|$)|\/)/.test(query); +const isDrive = (part: string | undefined) => !!part && /^[A-Za-z]:$/.test(part); + /** `rel` (as typed after `@`) resolved against `root`, `.` and `..` folded lexically. */ export function resolveTyped(root: string, rel: string): string { const out: string[] = []; - for (const part of (rel.startsWith("/") ? rel : `${root}/${rel}`).split("/")) { - if (part === "..") out.pop(); - else if (part && part !== ".") out.push(part); + const path = rel.startsWith("/") ? rel : `${root.replace(/\\/g, "/")}/${rel}`; + for (const part of path.split("/")) { + if (part === "..") { + // Never fold away a Windows drive (`C:`). + if (out.length > 1 || !isDrive(out[0])) out.pop(); + } else if (part && part !== ".") out.push(part); } - return `/${out.join("/")}`; + return isDrive(out[0]) ? out.join("/") : `/${out.join("/")}`; } /** `@rel` with a line range suffix when given ("@src/a.rs:10-20"). */