fix(tui): open @ file mentions inside slash command arguments (#1223)

Typing @ in the middle of a slash command argument (for example `/goal Fix the @checkout docs`) was swallowed by the slash-argument completion guard before the @ mention branch ran, so the file list never opened. Run the @ mention branch ahead of the slash guards so file mentions take priority; plain slash-argument editing is still suppressed as before.
This commit is contained in:
liruifengv 2026-06-30 15:35:19 +08:00 committed by GitHub
parent 7f61488a88
commit 80e6888e34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 39 additions and 14 deletions

View file

@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---
Fix @ file mentions not opening when typed inside a slash command argument.

View file

@ -67,20 +67,11 @@ export class FileMentionProvider implements AutocompleteProvider {
const currentLine = lines[cursorLine] ?? '';
const textBeforeCursor = currentLine.slice(0, cursorCol);
if (shouldSuppressLeadingWhitespaceSlashPath(textBeforeCursor, options.force)) {
return null;
}
if (
shouldSuppressSlashArgumentCompletion(
textBeforeCursor,
currentLine.slice(cursorCol),
options.force,
)
) {
return null;
}
// `@` file / folder mentions take priority over the slash-command guards
// below. Without this, typing `@` inside a slash command's argument text
// (e.g. `/goal Fix the @|checkout docs`) would be swallowed by
// `shouldSuppressSlashArgumentCompletion` before the mention branch ever
// runs, so the file list never opens.
const atPrefix = extractAtPrefix(textBeforeCursor);
if (atPrefix !== null) {
if (this.fdPath === null || this.additionalDirs.length > 0) {
@ -104,6 +95,20 @@ export class FileMentionProvider implements AutocompleteProvider {
}
}
if (shouldSuppressLeadingWhitespaceSlashPath(textBeforeCursor, options.force)) {
return null;
}
if (
shouldSuppressSlashArgumentCompletion(
textBeforeCursor,
currentLine.slice(cursorCol),
options.force,
)
) {
return null;
}
// Handle slash-command name completion ourselves so that aliases are
// searchable and visible in the label.
if (!options.force && textBeforeCursor.startsWith('/')) {

View file

@ -99,6 +99,21 @@ describe('FileMentionProvider', () => {
expect(result).toBeNull();
});
it('opens @ file mention when typed in the middle of a slash command argument', async () => {
writeFileSync(join(workDir, 'README.md'), 'readme');
const provider = new FileMentionProvider([GOAL_COMMAND], workDir, NO_FD);
// Cursor sits in the middle of the /goal argument text, right after a
// freshly typed `@`. The slash-argument guard must not suppress the @
// file list here.
const line = '/goal Fix the @checkout docs';
const result = await provider.getSuggestions([line], 0, '/goal Fix the @'.length, {
signal: ctrl(),
});
expect(result).not.toBeNull();
expect(result!.prefix).toBe('@');
expect(result!.items.map((item) => item.value)).toContain('@README.md');
});
it('still completes slash arguments at the end of an empty argument', async () => {
const provider = new FileMentionProvider([GOAL_COMMAND], workDir, NO_FD);
const line = '/goal ';