Skip to content

Commit 598791e

Browse files
committed
fix(chat): distinguish a line-less file-selection label from the whole file
Cursor Bugbot: a rich-markdown selection labelled itself with the bare file name, which is exactly the whole-file chip's label. Menu-driven inserts reject any context whose label is already taken (isContextAlreadySelected closes the menu silently), so once a markdown selection was attached, mentioning that same file was quietly dropped. One-way: the reverse order works because programmatic inserts ordinalize through prepareContextForInsert. Fallen out of dropping the fabricated line range from this editor — with no range left, the label collapsed onto the file name. Fixed at the single source: buildFileSelectionLabel now returns 'notes.md (selection)' when there is no line range, so it stays honest about location while remaining distinguishable.
1 parent 8455da9 commit 598791e

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

apps/sim/lib/copilot/chat/selection-context.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ describe('buildFileSelectionLabel', () => {
2222
expect(buildFileSelectionLabel('notes.md', 12)).toBe('notes.md:12')
2323
})
2424

25-
it('falls back to just the file name when the source has no line numbers', () => {
26-
expect(buildFileSelectionLabel('notes.md')).toBe('notes.md')
25+
it('marks a line-less selection so it cannot collide with the whole-file chip', () => {
26+
// A bare 'notes.md' would equal the whole-file chip's label, and menu inserts
27+
// silently reject an already-taken label — blocking the file's own mention.
28+
expect(buildFileSelectionLabel('notes.md')).toBe('notes.md (selection)')
29+
expect(buildFileSelectionLabel('notes.md')).not.toBe('notes.md')
2730
})
2831
})
2932

apps/sim/lib/copilot/chat/selection-context.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@ export function truncateSelectionText(text: string): string {
4444
}
4545

4646
/**
47-
* Builds the IDE-style chip label for a file selection, e.g. `notes.md:12-40`,
48-
* `notes.md:12`, or just `notes.md` when the source has no line numbers (the
49-
* rich-markdown editor, whose document model has no source lines).
47+
* Builds the IDE-style chip label for a file selection, e.g. `notes.md:12-40` or
48+
* `notes.md:12`. Without a line range — the rich-markdown editor, whose document
49+
* model has no source lines — it falls back to `notes.md (selection)`.
50+
*
51+
* That suffix is load-bearing, not decoration: a bare file name would be
52+
* identical to the whole-file `@notes.md` chip's label, and menu-driven inserts
53+
* reject any context whose label is already taken (`isContextAlreadySelected`).
54+
* A markdown selection would then silently block mentioning its own file.
5055
*
5156
* Kept ASCII so the label survives being inserted as an inline mention token in
5257
* the chat input. Labels must be unique across a message's chips — the caller
@@ -57,7 +62,7 @@ export function buildFileSelectionLabel(
5762
startLine?: number,
5863
endLine?: number
5964
): string {
60-
if (!startLine) return fileName
65+
if (!startLine) return `${fileName} (selection)`
6166
const range = endLine && endLine !== startLine ? `${startLine}-${endLine}` : `${startLine}`
6267
return `${fileName}:${range}`
6368
}

0 commit comments

Comments
 (0)