Skip to content

Commit c798d25

Browse files
fix(web): Convert file references to full browse URLs in portable markdown
Change convertLLMOutputToPortableMarkdown to embed full browse URLs instead of relative file paths, so users can click links without needing an IDE open. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 880c8e0 commit c798d25

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

packages/web/src/app/api/(server)/chat/blocking/route.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ export const POST = apiHandler(async (request: NextRequest) => {
182182
: undefined;
183183
const answerText = answerPart?.text ?? '';
184184

185-
// Convert to portable markdown (replaces @file: references with markdown links)
186-
const portableAnswer = convertLLMOutputToPortableMarkdown(answerText);
187-
188-
// Build the chat URL
185+
// Build the base URL and chat URL
189186
const baseUrl = env.AUTH_URL;
187+
188+
// Convert to portable markdown (replaces @file: references with markdown links)
189+
const portableAnswer = convertLLMOutputToPortableMarkdown(answerText, baseUrl);
190190
const chatUrl = `${baseUrl}/${org.domain}/chat/${chat.id}`;
191191

192192
logger.debug(`Completed blocking agent for chat ${chat.id}`, {

packages/web/src/features/chat/components/chatThread/answerCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ const AnswerCardComponent = forwardRef<HTMLDivElement, AnswerCardProps>(({
5151
);
5252

5353
const onCopyAnswer = useCallback(() => {
54-
const markdownText = convertLLMOutputToPortableMarkdown(answerText);
54+
const baseUrl = typeof window !== 'undefined' ? window.location.origin : '';
55+
const markdownText = convertLLMOutputToPortableMarkdown(answerText, baseUrl);
5556
navigator.clipboard.writeText(markdownText);
5657
toast({
5758
description: "✅ Copied to clipboard",

packages/web/src/features/chat/utils.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { CreateUIMessage, TextUIPart, UIMessagePart } from "ai";
22
import { Descendant, Editor, Point, Range, Transforms } from "slate";
33
import { ANSWER_TAG, FILE_REFERENCE_PREFIX, FILE_REFERENCE_REGEX } from "./constants";
4+
import { getBrowsePath, BrowseHighlightRange } from "@/app/[domain]/browse/hooks/utils";
5+
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants";
46
import {
57
CustomEditor,
68
CustomText,
@@ -243,10 +245,10 @@ export const createFileReference = ({ repo, path, startLine, endLine }: { repo:
243245
* Markdown format. Practically, this means converting references into Markdown
244246
* links and removing the answer tag.
245247
*/
246-
export const convertLLMOutputToPortableMarkdown = (text: string): string => {
248+
export const convertLLMOutputToPortableMarkdown = (text: string, baseUrl: string): string => {
247249
return text
248250
.replace(ANSWER_TAG, '')
249-
.replace(FILE_REFERENCE_REGEX, (_, _repo, fileName, startLine, endLine) => {
251+
.replace(FILE_REFERENCE_REGEX, (_, repo, fileName, startLine, endLine) => {
250252
const displayName = fileName.split('/').pop() || fileName;
251253

252254
let linkText = displayName;
@@ -258,7 +260,23 @@ export const convertLLMOutputToPortableMarkdown = (text: string): string => {
258260
}
259261
}
260262

261-
return `[${linkText}](${fileName})`;
263+
// Construct highlight range for line numbers
264+
const highlightRange: BrowseHighlightRange | undefined = startLine ? {
265+
start: { lineNumber: parseInt(startLine) },
266+
end: { lineNumber: parseInt(endLine || startLine) },
267+
} : undefined;
268+
269+
// Construct full browse URL
270+
const browsePath = getBrowsePath({
271+
repoName: repo,
272+
path: fileName,
273+
pathType: 'blob',
274+
domain: SINGLE_TENANT_ORG_DOMAIN,
275+
highlightRange,
276+
});
277+
278+
const fullUrl = `${baseUrl}${browsePath}`;
279+
return `[${linkText}](${fullUrl})`;
262280
})
263281
.trim();
264282
}

0 commit comments

Comments
 (0)