Skip to content

Commit 6902c54

Browse files
committed
replace input instead of appending on autocomplete
1 parent 05e36dd commit 6902c54

File tree

2 files changed

+98
-7
lines changed

2 files changed

+98
-7
lines changed

cli/src/state/atoms/__tests__/keyboard.test.ts

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ describe("keypress atoms", () => {
359359
expect(text).toBe("/mode")
360360
})
361361

362-
it("should complete argument by appending only missing part", () => {
362+
it("should complete argument by replacing partial text", () => {
363363
// Type '/mode tes' - this will automatically trigger autocomplete
364364
const input = "/mode tes"
365365
for (const char of input) {
@@ -398,11 +398,96 @@ describe("keypress atoms", () => {
398398
}
399399
store.set(keyboardHandlerAtom, tabKey)
400400

401-
// Should append only 't' to complete '/mode test'
401+
// Should replace 'tes' with 'test' to complete '/mode test'
402402
const text = store.get(textBufferStringAtom)
403403
expect(text).toBe("/mode test")
404404
})
405405

406+
it("should replace partial argument with full suggestion", () => {
407+
// Bug fix: Type '/model info gpt' with suggestion 'openai/gpt-5'
408+
// This test verifies the fix where Tab was incorrectly appending instead of replacing
409+
const input = "/model info gpt"
410+
for (const char of input) {
411+
const key: Key = {
412+
name: char,
413+
sequence: char,
414+
ctrl: false,
415+
meta: false,
416+
shift: false,
417+
paste: false,
418+
}
419+
store.set(keyboardHandlerAtom, key)
420+
}
421+
422+
// Set up argument suggestions
423+
const mockArgumentSuggestion: ArgumentSuggestion = {
424+
value: "openai/gpt-5",
425+
description: "OpenAI GPT-5 model",
426+
matchScore: 90,
427+
highlightedValue: "openai/gpt-5",
428+
}
429+
store.set(argumentSuggestionsAtom, [mockArgumentSuggestion])
430+
store.set(suggestionsAtom, []) // No command suggestions
431+
store.set(selectedIndexAtom, 0)
432+
433+
// Press Tab
434+
const tabKey: Key = {
435+
name: "tab",
436+
sequence: "\t",
437+
ctrl: false,
438+
meta: false,
439+
shift: false,
440+
paste: false,
441+
}
442+
store.set(keyboardHandlerAtom, tabKey)
443+
444+
// Should replace 'gpt' with 'openai/gpt-5' (not append to get 'gptopenai/gpt-5')
445+
const text = store.get(textBufferStringAtom)
446+
expect(text).toBe("/model info openai/gpt-5")
447+
})
448+
449+
it("should complete argument from empty with trailing space", () => {
450+
// Type '/model info ' (with trailing space)
451+
const input = "/model info "
452+
for (const char of input) {
453+
const key: Key = {
454+
name: char,
455+
sequence: char,
456+
ctrl: false,
457+
meta: false,
458+
shift: false,
459+
paste: false,
460+
}
461+
store.set(keyboardHandlerAtom, key)
462+
}
463+
464+
// Set up argument suggestions
465+
const mockArgumentSuggestion: ArgumentSuggestion = {
466+
value: "openai/gpt-4",
467+
description: "OpenAI GPT-4 model",
468+
matchScore: 100,
469+
highlightedValue: "openai/gpt-4",
470+
}
471+
store.set(argumentSuggestionsAtom, [mockArgumentSuggestion])
472+
store.set(suggestionsAtom, [])
473+
store.set(selectedIndexAtom, 0)
474+
475+
// Press Tab
476+
const tabKey: Key = {
477+
name: "tab",
478+
sequence: "\t",
479+
ctrl: false,
480+
meta: false,
481+
shift: false,
482+
paste: false,
483+
}
484+
store.set(keyboardHandlerAtom, tabKey)
485+
486+
// Should add the full suggestion value
487+
const text = store.get(textBufferStringAtom)
488+
expect(text).toBe("/model info openai/gpt-4")
489+
})
490+
406491
it("should handle exact match completion", () => {
407492
// Type '/help' - this will automatically trigger autocomplete
408493
const input = "/help"

cli/src/state/atoms/keyboard.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,17 @@ function handleAutocompleteKeys(get: any, set: any, key: Key): void {
487487
const suggestion = allSuggestions[selectedIndex]
488488
const currentText = get(textBufferStringAtom)
489489

490-
// Get only the missing part to append
491-
const completionText = getCompletionText(currentText, suggestion)
492-
493-
// Insert the completion text
494-
set(insertTextAtom, completionText)
490+
// For argument suggestions, replace the entire input with formatted suggestion
491+
// For command suggestions, append the completion text
492+
if ("command" in suggestion) {
493+
// CommandSuggestion - append only the missing part
494+
const completionText = getCompletionText(currentText, suggestion)
495+
set(insertTextAtom, completionText)
496+
} else {
497+
// ArgumentSuggestion - replace entire input to avoid duplication
498+
const newText = formatSuggestion(suggestion, currentText)
499+
set(setTextAtom, newText)
500+
}
495501
}
496502
return
497503

0 commit comments

Comments
 (0)