diff --git a/CHANGELOG.md b/CHANGELOG.md index e156d9e87..8d9e5aa0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `nanoid` to `^3.3.18`. [#1557](https://github.com/sourcebot-dev/sourcebot/pull/1557) - Upgraded `dompurify` to `^3.4.13`. [#1556](https://github.com/sourcebot-dev/sourcebot/pull/1556) - Upgraded `mermaid` to `^11.16.1`. [#1555](https://github.com/sourcebot-dev/sourcebot/pull/1555) +- [EE] Fixed Ask Sourcebot file reference citations for repositories whose code host URL includes a port. [#1565](https://github.com/sourcebot-dev/sourcebot/pull/1565) ## [5.1.5] - 2026-07-31 diff --git a/packages/web/src/ee/features/chat/components/chatThread/markdownRenderer.tsx b/packages/web/src/ee/features/chat/components/chatThread/markdownRenderer.tsx index 012e1e682..b83b2d369 100644 --- a/packages/web/src/ee/features/chat/components/chatThread/markdownRenderer.tsx +++ b/packages/web/src/ee/features/chat/components/chatThread/markdownRenderer.tsx @@ -49,7 +49,7 @@ function remarkReferencesPlugin() { return function (tree: Nodes) { findAndReplace(tree, [ FILE_REFERENCE_REGEX, - (_, repo: string, fileName: string, startLine?: string, endLine?: string) => { + (_, repo: string, _port: string | undefined, fileName: string, startLine?: string, endLine?: string) => { // Create display text let displayText = fileName.split('/').pop() ?? fileName; @@ -290,4 +290,4 @@ const MarkdownRendererComponent = forwardRef { FILE_REFERENCE_REGEX.lastIndex = 0; let match: RegExpExecArray | null; while ((match = FILE_REFERENCE_REGEX.exec(text)) !== null) { - const [, repo, path] = match; + const [, repo, , path] = match; if (!repo || !path) { continue; } diff --git a/packages/web/src/ee/features/chat/skills/components/skillInstructionsEditor.tsx b/packages/web/src/ee/features/chat/skills/components/skillInstructionsEditor.tsx index 3930a056f..ce137876a 100644 --- a/packages/web/src/ee/features/chat/skills/components/skillInstructionsEditor.tsx +++ b/packages/web/src/ee/features/chat/skills/components/skillInstructionsEditor.tsx @@ -44,7 +44,7 @@ const parseInlineInstructions = (text: string): Descendant[] => { FILE_REFERENCE_REGEX.lastIndex = 0; let match: RegExpExecArray | null; while ((match = FILE_REFERENCE_REGEX.exec(text)) !== null) { - const [rawReference, repo, path] = match; + const [rawReference, repo, , path] = match; if (!repo || !path) { continue; } diff --git a/packages/web/src/ee/features/chat/useExtractPanelItems.ts b/packages/web/src/ee/features/chat/useExtractPanelItems.ts index 434ba7215..db5946642 100644 --- a/packages/web/src/ee/features/chat/useExtractPanelItems.ts +++ b/packages/web/src/ee/features/chat/useExtractPanelItems.ts @@ -70,7 +70,7 @@ export const useExtractPanelItems = ( const combined = new RegExp(`${MERMAID_BLOCK_REGEX.source}|${FILE_REFERENCE_REGEX.source}`, 'g'); let match: RegExpExecArray | null; while ((match = combined.exec(text)) !== null) { - // match[1]: mermaid body. match[2..5]: file reference repo/path/start/end. + // match[1]: mermaid body. match[2..6]: file reference repo/port/path/start/end. if (match[1] !== undefined) { const code = match[1].trim(); if (!code) { @@ -85,8 +85,8 @@ export const useExtractPanelItems = ( const diagramIndex = diagrams.length; diagrams.push(diagram); orderedItems.push({ kind: 'diagram', diagram, diagramIndex }); - } else if (match[2] !== undefined && match[3] !== undefined) { - const reference = createFileReference({ repo: match[2], path: match[3], startLine: match[4], endLine: match[5] }); + } else if (match[2] !== undefined && match[4] !== undefined) { + const reference = createFileReference({ repo: match[2], path: match[4], startLine: match[5], endLine: match[6] }); const source = tryResolveFileReference(reference, referencedFileSources); if (!source) { continue; diff --git a/packages/web/src/ee/features/chat/useExtractReferences.ts b/packages/web/src/ee/features/chat/useExtractReferences.ts index 7ab3eebe0..05c819006 100644 --- a/packages/web/src/ee/features/chat/useExtractReferences.ts +++ b/packages/web/src/ee/features/chat/useExtractReferences.ts @@ -19,7 +19,7 @@ export const useExtractReferences = (part?: TextUIPart) => { let match; while ((match = FILE_REFERENCE_REGEX.exec(content ?? '')) !== null && match !== null) { - const [_, repo, fileName, startLine, endLine] = match; + const [, repo, , fileName, startLine, endLine] = match; const fileReference = createFileReference({ repo: repo, diff --git a/packages/web/src/features/chat/constants.ts b/packages/web/src/features/chat/constants.ts index ed38c07a3..99e3083f4 100644 --- a/packages/web/src/features/chat/constants.ts +++ b/packages/web/src/features/chat/constants.ts @@ -1,7 +1,7 @@ export const FILE_REFERENCE_PREFIX = '@file:'; export const FILE_REFERENCE_REGEX = new RegExp( // @file:{repoName::fileName:startLine-endLine} - `${FILE_REFERENCE_PREFIX}\\{([^:}]+)::([^:}]+)(?::(\\d+)(?:-(\\d+))?)?\\}`, + `${FILE_REFERENCE_PREFIX}\\{([^:}]+(:\\d+)?[^:}]*)::([^:}]+)(?::(\\d+)(?:-(\\d+))?)?\\}`, 'g' ); diff --git a/packages/web/src/features/chat/utils.test.ts b/packages/web/src/features/chat/utils.test.ts index bf598a25e..4e73bbb24 100644 --- a/packages/web/src/features/chat/utils.test.ts +++ b/packages/web/src/features/chat/utils.test.ts @@ -134,6 +134,27 @@ test('fileReferenceToString matches FILE_REFERENCE_REGEX', () => { }))).toBe(true); }); +test('fileReferenceToString matches FILE_REFERENCE_REGEX for repos with ports', () => { + const reference = fileReferenceToString({ + repo: 'git.example.com:8080/org/repo', + path: 'auth.ts', + range: { + startLine: 45, + endLine: 60, + }, + }); + + FILE_REFERENCE_REGEX.lastIndex = 0; + const match = FILE_REFERENCE_REGEX.exec(reference); + + expect(match).not.toBeNull(); + expect(match?.[1]).toBe('git.example.com:8080/org/repo'); + expect(match?.[2]).toBe(':8080'); + expect(match?.[3]).toBe('auth.ts'); + expect(match?.[4]).toBe('45'); + expect(match?.[5]).toBe('60'); +}); + test('slateContentToString serializes command mentions as literal slash commands', () => { const children = [{ type: 'paragraph', diff --git a/packages/web/src/features/chat/utils.ts b/packages/web/src/features/chat/utils.ts index 23cd08590..54f0f0e15 100644 --- a/packages/web/src/features/chat/utils.ts +++ b/packages/web/src/features/chat/utils.ts @@ -284,7 +284,7 @@ export const createFileReference = ({ repo, path, startLine, endLine }: { repo: export const convertLLMOutputToPortableMarkdown = (text: string, baseUrl: string, sources: FileSource[]): string => { return text .replace(ANSWER_TAG, '') - .replace(FILE_REFERENCE_REGEX, (_, repo, fileName, startLine, endLine) => { + .replace(FILE_REFERENCE_REGEX, (_, repo, _port, fileName, startLine, endLine) => { const reference = createFileReference({ repo, path: fileName,