diff --git a/packages/app/src/utils/inline-path.test.ts b/packages/app/src/utils/inline-path.test.ts index 4aca58ca3..a641a897d 100644 --- a/packages/app/src/utils/inline-path.test.ts +++ b/packages/app/src/utils/inline-path.test.ts @@ -84,6 +84,19 @@ describe("parseAssistantFileLink", () => { }); }); + it("parses absolute POSIX hrefs with VS Code-style line suffixes inside the active workspace", () => { + expect( + parseAssistantFileLink("/Users/test/project/src/app.tsx:33", { + workspaceRoot: "/Users/test/project", + }), + ).toEqual({ + raw: "/Users/test/project/src/app.tsx:33", + path: "/Users/test/project/src/app.tsx", + lineStart: 33, + lineEnd: undefined, + }); + }); + it("parses absolute Windows hrefs inside the active workspace", () => { expect( parseAssistantFileLink("C:/repo/src/app.tsx#L12-L20", { @@ -97,6 +110,19 @@ describe("parseAssistantFileLink", () => { }); }); + it("parses absolute Windows hrefs with VS Code-style line suffixes inside the active workspace", () => { + expect( + parseAssistantFileLink("C:/repo/src/app.tsx:12-20", { + workspaceRoot: "C:/repo", + }), + ).toEqual({ + raw: "C:/repo/src/app.tsx:12-20", + path: "C:/repo/src/app.tsx", + lineStart: 12, + lineEnd: 20, + }); + }); + it("allows file URLs even when they are outside the workspace root", () => { expect( parseAssistantFileLink("file:///tmp/outside.txt", { diff --git a/packages/app/src/utils/inline-path.ts b/packages/app/src/utils/inline-path.ts index d30f01a2b..6dfa47fb5 100644 --- a/packages/app/src/utils/inline-path.ts +++ b/packages/app/src/utils/inline-path.ts @@ -166,6 +166,21 @@ export function parseAssistantFileLink( return null; } + const inlinePathTarget = parseInlinePathToken(trimmed); + if (inlinePathTarget) { + const normalizedPath = normalizePathToken(inlinePathTarget.path); + if ( + normalizedPath && + isAbsolutePath(normalizedPath) && + isAllowedAbsolutePath(normalizedPath, options.workspaceRoot) + ) { + return { + ...inlinePathTarget, + path: normalizedPath, + }; + } + } + const windowsPathMatch = trimmed.match(/^([A-Za-z]:[\\/][^?#]*)(#[^?]+)?$/); if (windowsPathMatch) { const normalizedPath = normalizePathToken(windowsPathMatch[1] ?? "");