From 7c0338a53cef53bbf33e9457caac5aee65a90ca1 Mon Sep 17 00:00:00 2001 From: Yarco Wang Date: Fri, 23 Oct 2026 11:12:46 +0800 Subject: [PATCH 1/3] feat(chat): add prompt history picker to the chat input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A leading "!" or "!" in the chat input opens a picker with the prompts of the current task, newest first. A query after the trigger filters the list with fuzzy matching, for example !fix. Selecting a row replaces the whole input with that prompt. It does not send the message, so the user can edit the text first. Escape closes the picker. The picker does not open for an exclamation mark inside a message ("Great!", "if (!x)") or for a markdown image ("![alt](url)"). The input placeholder now shows "! for user history" between the command hint and the drag hint. All 18 locales carry the new chat:historyHint key. --- .../src/components/chat/ChatTextArea.tsx | 90 ++++++++++++++++--- .../src/components/chat/ContextMenu.tsx | 33 ++++++- .../chat/__tests__/ChatTextArea.spec.tsx | 46 ++++++++++ webview-ui/src/i18n/locales/ca/chat.json | 1 + webview-ui/src/i18n/locales/de/chat.json | 1 + webview-ui/src/i18n/locales/en/chat.json | 1 + webview-ui/src/i18n/locales/es/chat.json | 1 + webview-ui/src/i18n/locales/fr/chat.json | 1 + webview-ui/src/i18n/locales/hi/chat.json | 1 + webview-ui/src/i18n/locales/id/chat.json | 1 + webview-ui/src/i18n/locales/it/chat.json | 1 + webview-ui/src/i18n/locales/ja/chat.json | 1 + webview-ui/src/i18n/locales/ko/chat.json | 1 + webview-ui/src/i18n/locales/nl/chat.json | 1 + webview-ui/src/i18n/locales/pl/chat.json | 1 + webview-ui/src/i18n/locales/pt-BR/chat.json | 1 + webview-ui/src/i18n/locales/ru/chat.json | 1 + webview-ui/src/i18n/locales/tr/chat.json | 1 + webview-ui/src/i18n/locales/vi/chat.json | 1 + webview-ui/src/i18n/locales/zh-CN/chat.json | 1 + webview-ui/src/i18n/locales/zh-TW/chat.json | 1 + .../utils/__tests__/context-mentions.spec.ts | 66 ++++++++++++++ webview-ui/src/utils/context-mentions.ts | 44 +++++++++ 23 files changed, 284 insertions(+), 13 deletions(-) diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 61419487cc..cccf60da3a 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -16,6 +16,7 @@ import { ContextMenuOptionType, getContextMenuOptions, insertMention, + isHistoryTrigger, removeMention, shouldShowContextMenu, SearchResult, @@ -231,14 +232,21 @@ export const ChatTextArea = forwardRef( const [isEnhancingPrompt, setIsEnhancingPrompt] = useState(false) const [isFocused, setIsFocused] = useState(false) + // Text for which the user explicitly dismissed the prompt history picker. + // Without this, recalling (or typing) a message that starts with "!" would + // pop the picker back open on the very next keystroke. + const suppressedHistoryRef = useRef(null) + // Use custom hook for prompt history navigation - const { handleHistoryNavigation, resetHistoryNavigation, resetOnInputChange } = usePromptHistory({ - clineMessages, - taskHistory, - cwd, - inputValue: normalizedInputValue, - setInputValue, - }) + const { handleHistoryNavigation, resetHistoryNavigation, resetOnInputChange, promptHistory } = usePromptHistory( + { + clineMessages, + taskHistory, + cwd, + inputValue: normalizedInputValue, + setInputValue, + }, + ) // Fetch git commits when Git is selected or when typing a hash. useEffect(() => { @@ -326,6 +334,27 @@ export const ChatTextArea = forwardRef( return } + if (type === ContextMenuOptionType.History && value) { + // Replace the whole input with the recalled prompt instead of + // inserting it as a mention: the "!" prefix is only a trigger + // and must not survive into the message. Deliberately does not + // send, so the user can edit the prompt before re-sending. + suppressedHistoryRef.current = value + setShowContextMenu(false) + setSelectedType(null) + setSelectedMenuIndex(-1) + setSearchQuery("") + setInputValue(value) + setCursorPosition(value.length) + setIntendedCursorPosition(value.length) + resetHistoryNavigation() + + setTimeout(() => { + textAreaRef.current?.focus() + }, 0) + return + } + if (type === ContextMenuOptionType.Mode && value) { // Handle mode selection. setMode(value) @@ -421,8 +450,14 @@ export const ChatTextArea = forwardRef( (event: React.KeyboardEvent) => { if (showContextMenu) { if (event.key === "Escape") { + // Dismiss the menu outright. `!` is easy to type by + // accident, so Escape must actually close the picker + // rather than leave the arrow keys captured by it. + suppressedHistoryRef.current = normalizedInputValue + setShowContextMenu(false) + setSearchQuery("") setSelectedType(null) - setSelectedMenuIndex(3) // File by default + setSelectedMenuIndex(-1) return } @@ -437,6 +472,7 @@ export const ChatTextArea = forwardRef( fileSearchResults, allModes, commands, + promptHistory, ) const optionsLength = options.length @@ -475,6 +511,7 @@ export const ChatTextArea = forwardRef( fileSearchResults, allModes, commands, + promptHistory, )[selectedMenuIndex] if ( selectedOption && @@ -576,6 +613,7 @@ export const ChatTextArea = forwardRef( handleHistoryNavigation, resetHistoryNavigation, commands, + promptHistory, enterBehavior, ], ) @@ -602,10 +640,31 @@ export const ChatTextArea = forwardRef( setCursorPosition(newCursorPosition) const showMenu = shouldShowContextMenu(newValue, newCursorPosition) + + if (isHistoryTrigger(newValue)) { + const suppressed = suppressedHistoryRef.current + + // Keep the picker closed when the user dismissed it for this text, + // or when there is nothing to recall. Without the second guard an + // empty picker would swallow Enter for a message starting with "!". + if ((suppressed !== null && newValue.startsWith(suppressed)) || promptHistory.length === 0) { + setShowContextMenu(false) + setSearchQuery("") + setSelectedMenuIndex(-1) + return + } + } else { + suppressedHistoryRef.current = null + } + setShowContextMenu(showMenu) if (showMenu) { - if (newValue.startsWith("/") && !newValue.includes(" ")) { + if (isHistoryTrigger(newValue)) { + // getContextMenuOptions dispatches on the leading "!" itself. + setSearchQuery(newValue) + setSelectedMenuIndex(0) + } else if (newValue.startsWith("/") && !newValue.includes(" ")) { // Handle slash command - request fresh commands const query = newValue setSearchQuery(query) @@ -655,7 +714,14 @@ export const ChatTextArea = forwardRef( setFileSearchResults([]) // Clear file search results. } }, - [setInputValue, setSearchRequestId, setFileSearchResults, setSearchLoading, resetOnInputChange], + [ + setInputValue, + setSearchRequestId, + setFileSearchResults, + setSearchLoading, + resetOnInputChange, + promptHistory, + ], ) useEffect(() => { @@ -935,7 +1001,8 @@ export const ChatTextArea = forwardRef( } }) - const placeholderBottomText = `\n(${t("chat:addContext")}${shouldDisableImages ? `, ${t("chat:dragFiles")}` : `, ${t("chat:dragFilesImages")}`})` + const dragHint = shouldDisableImages ? t("chat:dragFiles") : t("chat:dragFilesImages") + const placeholderBottomText = `\n(${t("chat:addContext")}, ${t("chat:historyHint")}, ${dragHint})` // Common mode selector handler const handleModeChange = useCallback( @@ -1016,6 +1083,7 @@ export const ChatTextArea = forwardRef( loading={searchLoading} dynamicSearchResults={fileSearchResults} commands={commands} + history={promptHistory} /> )} diff --git a/webview-ui/src/components/chat/ContextMenu.tsx b/webview-ui/src/components/chat/ContextMenu.tsx index 04ceb2eab6..019d0d6235 100644 --- a/webview-ui/src/components/chat/ContextMenu.tsx +++ b/webview-ui/src/components/chat/ContextMenu.tsx @@ -30,6 +30,7 @@ interface ContextMenuProps { loading?: boolean dynamicSearchResults?: SearchResult[] commands?: Command[] + history?: string[] } const ContextMenu: React.FC = ({ @@ -43,13 +44,22 @@ const ContextMenu: React.FC = ({ modes, dynamicSearchResults = [], commands = [], + history = [], }) => { const [materialIconsBaseUri, setMaterialIconsBaseUri] = useState("") const menuRef = useRef(null) const filteredOptions = useMemo(() => { - return getContextMenuOptions(searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands) - }, [searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands]) + return getContextMenuOptions( + searchQuery, + selectedType, + queryItems, + dynamicSearchResults, + modes, + commands, + history, + ) + }, [searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands, history]) useEffect(() => { if (menuRef.current) { @@ -138,6 +148,23 @@ const ContextMenu: React.FC = ({ )} ) + case ContextMenuOptionType.History: + // Prompts can be long and multi-line; keep every row to one line so + // the picker stays scannable. The full text lands in the input on + // selection, and line breaks become visible there. + return ( + + {option.value?.replace(/\s+/g, " ").trim()} + + ) case ContextMenuOptionType.Problems: return {t("chat:contextMenu.problems")} case ContextMenuOptionType.Terminal: @@ -230,6 +257,8 @@ const ContextMenu: React.FC = ({ return "link" case ContextMenuOptionType.Git: return "git-commit" + case ContextMenuOptionType.History: + return "history" case ContextMenuOptionType.NoResults: return "info" default: diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx index 5cced6a92f..0d8583e676 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx @@ -634,6 +634,52 @@ describe("ChatTextArea", () => { expect(setInputValue).toHaveBeenCalledWith("New input") }) + it("should open the prompt history picker when typing a leading !", () => { + const setInputValue = vi.fn() + const onSend = vi.fn() + const { container } = render( + , + ) + + const textarea = container.querySelector("textarea")! + + fireEvent.change(textarea, { target: { value: "!", selectionStart: 1 } }) + + // Newest prompt first. + expect(container.textContent).toContain("Third prompt") + + fireEvent.keyDown(textarea, { key: "Enter" }) + + // Selecting only fills the input; it must not send the message. + expect(setInputValue).toHaveBeenCalledWith("Third prompt") + expect(onSend).not.toHaveBeenCalled() + }) + + it("should close the prompt history picker on Escape without sending", () => { + const onSend = vi.fn() + const { container } = render() + + const textarea = container.querySelector("textarea")! + + fireEvent.change(textarea, { target: { value: "!thi", selectionStart: 4 } }) + expect(container.textContent).toContain("Third prompt") + + fireEvent.keyDown(textarea, { key: "Escape" }) + + expect(container.textContent).not.toContain("Third prompt") + expect(onSend).not.toHaveBeenCalled() + }) + + it("should not open the prompt history picker for a mid-message exclamation mark", () => { + const { container } = render() + + const textarea = container.querySelector("textarea")! + + fireEvent.change(textarea, { target: { value: "Great!" } }) + + expect(container.textContent).not.toContain("Third prompt") + }) + it("should reset history navigation when sending message", () => { const onSend = vi.fn() const setInputValue = vi.fn() diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index d934d1105b..7529ee76ee 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Escriu un missatge...", "typeTask": "Escriu la teva tasca aquí...", "addContext": "@ per afegir context, / per a comandes", + "historyHint": "! per a l'historial d'usuari", "dragFiles": "manté premut shift per arrossegar fitxers", "dragFilesImages": "manté premut shift per arrossegar fitxers/imatges", "enhancePromptDescription": "El botó 'Millora la sol·licitud' ajuda a millorar la teva sol·licitud proporcionant context addicional, aclariments o reformulacions. Prova d'escriure una sol·licitud aquí i fes clic al botó de nou per veure com funciona.", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 1ac60a097e..847b81a6e4 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Nachricht eingeben...", "typeTask": "Gib deine Aufgabe hier ein...", "addContext": "@ für Kontext, / für Befehle", + "historyHint": "! für den Nutzerverlauf", "dragFiles": "Shift halten, um Dateien einzufügen", "dragFilesImages": "Shift halten, um Dateien/Bilder einzufügen", "enhancePromptDescription": "Die Schaltfläche 'Prompt verbessern' hilft, deine Anfrage durch zusätzlichen Kontext, Klarstellungen oder Umformulierungen zu verbessern. Versuche, hier eine Anfrage einzugeben und klicke erneut auf die Schaltfläche, um zu sehen, wie es funktioniert.", diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 51aee7a438..af58fdfce6 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -168,6 +168,7 @@ "typeMessage": "Type a message...", "typeTask": "Type your task here...", "addContext": "@ to add context, / for commands", + "historyHint": "! for user history", "dragFiles": "hold shift to drag in files", "dragFilesImages": "hold shift to drag in files/images", "errorReadingFile": "Error reading file", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index fbe66d6eb3..7ded7ac04d 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Escribe un mensaje...", "typeTask": "Escribe tu tarea aquí...", "addContext": "@ para agregar contexto, / para comandos", + "historyHint": "! para el historial de usuario", "dragFiles": "mantén shift para arrastrar archivos", "dragFilesImages": "mantén shift para arrastrar archivos/imágenes", "enhancePromptDescription": "El botón 'Mejorar el mensaje' ayuda a mejorar tu petición proporcionando contexto adicional, aclaraciones o reformulaciones. Intenta escribir una petición aquí y haz clic en el botón nuevamente para ver cómo funciona.", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index a8f5766c85..742a258c21 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Écrivez un message...", "typeTask": "Écrivez votre tâche ici...", "addContext": "@ pour ajouter du contexte, / pour les commandes", + "historyHint": "! pour l'historique utilisateur", "dragFiles": "maintenir Maj pour glisser des fichiers", "dragFilesImages": "maintenir Maj pour glisser des fichiers/images", "enhancePromptDescription": "Le bouton 'Améliorer la requête' aide à améliorer votre demande en fournissant un contexte supplémentaire, des clarifications ou des reformulations. Essayez de taper une demande ici et cliquez à nouveau sur le bouton pour voir comment cela fonctionne.", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index c6dbe9978d..69bb565579 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -132,6 +132,7 @@ "typeMessage": "एक संदेश लिखें...", "typeTask": "अपना कार्य यहां लिखें...", "addContext": "संदर्भ जोड़ने के लिए @, कमांड के लिए /", + "historyHint": "उपयोगकर्ता इतिहास के लिए !", "dragFiles": "फ़ाइलें खींचने के लिए shift दबाकर रखें", "dragFilesImages": "फ़ाइलें/चित्र खींचने के लिए shift दबाकर रखें", "enhancePromptDescription": "'प्रॉम्प्ट बढ़ाएँ' बटन अतिरिक्त संदर्भ, स्पष्टीकरण या पुनर्विचार प्रदान करके आपके अनुरोध को बेहतर बनाने में मदद करता है। यहां अनुरोध लिखकर देखें और यह कैसे काम करता है यह देखने के लिए बटन पर फिर से क्लिक करें।", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index c59be94c72..0432774197 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -171,6 +171,7 @@ "typeMessage": "Ketik pesan...", "typeTask": "Bangun, cari, tanya sesuatu", "addContext": "@ untuk menambah konteks, / untuk perintah", + "historyHint": "! untuk riwayat pengguna", "dragFiles": "tahan shift untuk drag file", "dragFilesImages": "tahan shift untuk drag file/gambar", "errorReadingFile": "Error membaca file", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index bb809a41b6..415c0afe33 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Scrivi un messaggio...", "typeTask": "Scrivi la tua attività qui...", "addContext": "@ per aggiungere contesto, / per i comandi", + "historyHint": "! per la cronologia utente", "dragFiles": "tieni premuto shift per trascinare file", "dragFilesImages": "tieni premuto shift per trascinare file/immagini", "enhancePromptDescription": "Il pulsante 'Migliora prompt' aiuta a migliorare la tua richiesta fornendo contesto aggiuntivo, chiarimenti o riformulazioni. Prova a digitare una richiesta qui e fai di nuovo clic sul pulsante per vedere come funziona.", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 18d7d0a7a8..2ad8c3fd8d 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -132,6 +132,7 @@ "typeMessage": "メッセージを入力...", "typeTask": "ここにタスクを入力...", "addContext": "コンテキスト追加は@、コマンドは/", + "historyHint": "ユーザー履歴は!", "dragFiles": "ファイルをドラッグするにはShiftキーを押したまま", "dragFilesImages": "ファイル/画像をドラッグするにはShiftキーを押したまま", "enhancePromptDescription": "「プロンプトを強化」ボタンは、追加コンテキスト、説明、または言い換えを提供することで、リクエストを改善します。ここにリクエストを入力し、ボタンを再度クリックして動作を確認してください。", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 95971b5e31..4797f68683 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -124,6 +124,7 @@ "typeMessage": "메시지 입력...", "typeTask": "여기에 작업 입력...", "addContext": "컨텍스트 추가는 @, 명령어는 /", + "historyHint": "사용자 기록은 !", "dragFiles": "파일을 드래그하려면 shift 키 누르기", "dragFilesImages": "파일/이미지를 드래그하려면 shift 키 누르기", "enhancePromptDescription": "'프롬프트 향상' 버튼은 추가 컨텍스트, 명확화 또는 재구성을 제공하여 요청을 개선합니다. 여기에 요청을 입력한 다음 버튼을 다시 클릭하여 작동 방식을 확인해보세요.", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index b8d2689327..b03ad81a97 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -141,6 +141,7 @@ "typeMessage": "Typ een bericht...", "typeTask": "Typ hier je taak...", "addContext": "@ om context toe te voegen, / voor commando's", + "historyHint": "! voor gebruikersgeschiedenis", "dragFiles": "houd shift ingedrukt om bestanden te slepen", "dragFilesImages": "houd shift ingedrukt om bestanden/afbeeldingen te slepen", "errorReadingFile": "Fout bij het lezen van bestand", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 1f8271f16e..578251defb 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Wpisz wiadomość...", "typeTask": "Wpisz swoje zadanie tutaj...", "addContext": "@ aby dodać kontekst, / dla poleceń", + "historyHint": "! dla historii użytkownika", "dragFiles": "przytrzymaj shift, aby przeciągnąć pliki", "dragFilesImages": "przytrzymaj shift, aby przeciągnąć pliki/obrazy", "enhancePromptDescription": "Przycisk 'Ulepsz podpowiedź' pomaga ulepszyć Twoją prośbę, dostarczając dodatkowy kontekst, wyjaśnienia lub przeformułowania. Spróbuj wpisać prośbę tutaj i kliknij przycisk ponownie, aby zobaczyć, jak to działa.", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 231cf54d70..51e86e92ee 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Digite uma mensagem...", "typeTask": "Digite sua tarefa aqui...", "addContext": "@ para adicionar contexto, / para comandos", + "historyHint": "! para o histórico do usuário", "dragFiles": "segure shift para arrastar arquivos", "dragFilesImages": "segure shift para arrastar arquivos/imagens", "enhancePromptDescription": "O botão 'Aprimorar prompt' ajuda a melhorar seu pedido fornecendo contexto adicional, esclarecimentos ou reformulações. Tente digitar um pedido aqui e clique no botão novamente para ver como funciona.", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 0bcb4176a3..1a07966463 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -141,6 +141,7 @@ "typeMessage": "Введите сообщение...", "typeTask": "Введите вашу задачу здесь...", "addContext": "@ для добавления контекста, / для команд", + "historyHint": "! для истории пользователя", "dragFiles": "удерживайте shift для перетаскивания файлов", "dragFilesImages": "удерживайте shift для перетаскивания файлов/изображений", "errorReadingFile": "Ошибка чтения файла", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 40c7d37b45..61d63b8107 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Bir mesaj yazın...", "typeTask": "Görevinizi buraya yazın...", "addContext": "Bağlam eklemek için @, komutlar için /", + "historyHint": "kullanıcı geçmişi için !", "dragFiles": "dosyaları sürüklemek için shift tuşuna basılı tutun", "dragFilesImages": "dosyaları/resimleri sürüklemek için shift tuşuna basılı tutun", "enhancePromptDescription": "'İstemi geliştir' düğmesi, ek bağlam, açıklama veya yeniden ifade sağlayarak isteğinizi iyileştirmeye yardımcı olur. Buraya bir istek yazıp düğmeye tekrar tıklayarak nasıl çalıştığını görebilirsiniz.", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index ef0bd5b59a..bdf942b4cb 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -132,6 +132,7 @@ "typeMessage": "Nhập tin nhắn...", "typeTask": "Nhập nhiệm vụ của bạn tại đây...", "addContext": "@ để thêm ngữ cảnh, / cho lệnh", + "historyHint": "! cho lịch sử người dùng", "dragFiles": "giữ shift để kéo tệp", "dragFilesImages": "giữ shift để kéo tệp/hình ảnh", "enhancePromptDescription": "Nút 'Nâng cao yêu cầu' giúp cải thiện yêu cầu của bạn bằng cách cung cấp ngữ cảnh bổ sung, làm rõ hoặc diễn đạt lại. Hãy thử nhập yêu cầu tại đây và nhấp vào nút một lần nữa để xem cách thức hoạt động.", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index b3e8f35297..ed73f3a2d3 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -132,6 +132,7 @@ "typeMessage": "输入消息...", "typeTask": "在此处输入您的任务...", "addContext": "@添加上下文,/输入命令", + "historyHint": "!查看历史", "dragFiles": "Shift+拖拽文件", "dragFilesImages": "Shift+拖拽文件/图片", "enhancePromptDescription": "'增强提示'按钮通过提供额外上下文、澄清或重新表述来帮助改进您的请求。尝试在此处输入请求,然后再次点击按钮查看其工作原理。", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 11a90a9178..e5982e7971 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -168,6 +168,7 @@ "typeMessage": "輸入訊息...", "typeTask": "在這裡輸入工作...", "addContext": "輸入 @ 新增內容,/ 執行命令", + "historyHint": "! 查看歷史", "dragFiles": "按住 Shift 鍵拖曳檔案", "dragFilesImages": "按住 Shift 鍵拖曳檔案/圖片", "errorReadingFile": "讀取檔案時發生錯誤", diff --git a/webview-ui/src/utils/__tests__/context-mentions.spec.ts b/webview-ui/src/utils/__tests__/context-mentions.spec.ts index 48b03907c3..4b716d83f0 100644 --- a/webview-ui/src/utils/__tests__/context-mentions.spec.ts +++ b/webview-ui/src/utils/__tests__/context-mentions.spec.ts @@ -586,3 +586,69 @@ describe("shouldShowContextMenu", () => { expect(shouldShowContextMenu("@/path/with space", 13)).toBe(false) // Cursor after unescaped space }) }) + +describe("prompt history trigger", () => { + it("should open the menu for a leading !", () => { + expect(shouldShowContextMenu("!", 1)).toBe(true) + expect(shouldShowContextMenu("!fix", 4)).toBe(true) + }) + + it("should open the menu for a leading full-width !", () => { + expect(shouldShowContextMenu("!", 1)).toBe(true) + expect(shouldShowContextMenu("!修复", 3)).toBe(true) + }) + + it("should not open the menu for ! outside the start of the input", () => { + expect(shouldShowContextMenu("Great!", 6)).toBe(false) + expect(shouldShowContextMenu("if (!x)", 7)).toBe(false) + expect(shouldShowContextMenu("![alt](url)", 11)).toBe(false) + expect(shouldShowContextMenu("多好!", 3)).toBe(false) + }) + + it("should close the menu once the message contains whitespace", () => { + expect(shouldShowContextMenu("!fix the bug", 12)).toBe(false) + expect(shouldShowContextMenu("! ", 2)).toBe(false) + }) +}) + +describe("getContextMenuOptions for prompt history", () => { + const history = ["Third prompt", "Second prompt", "First prompt"] + + it("should list prompts newest-first", () => { + const options = getContextMenuOptions("!", null, [], [], undefined, undefined, history) + expect(options.map((option) => option.type)).toEqual([ + ContextMenuOptionType.History, + ContextMenuOptionType.History, + ContextMenuOptionType.History, + ]) + expect(options.map((option) => option.value)).toEqual(["Third prompt", "Second prompt", "First prompt"]) + }) + + it("should filter prompts by the query", () => { + const options = getContextMenuOptions("!Third", null, [], [], undefined, undefined, history) + expect(options).toHaveLength(1) + expect(options[0]).toMatchObject({ type: ContextMenuOptionType.History, value: "Third prompt" }) + }) + + it("should drop duplicate prompts so the picker has no identical rows", () => { + const options = getContextMenuOptions("!", null, [], [], undefined, undefined, ["继续", "explain this", "继续"]) + expect(options.map((option) => option.value)).toEqual(["继续", "explain this"]) + }) + + it("should return NoResults when the history is empty", () => { + expect(getContextMenuOptions("!", null, [], [], undefined, undefined, [])).toEqual([ + { type: ContextMenuOptionType.NoResults }, + ]) + }) + + it("should return NoResults when nothing matches the query", () => { + expect(getContextMenuOptions("!zzzz", null, [], [], undefined, undefined, ["alpha", "beta"])).toEqual([ + { type: ContextMenuOptionType.NoResults }, + ]) + }) + + it("should not treat a mid-text exclamation mark as history", () => { + const options = getContextMenuOptions("Great!", null, [], [], undefined, undefined, history) + expect(options.every((option) => option.type !== ContextMenuOptionType.History)).toBe(true) + }) +}) diff --git a/webview-ui/src/utils/context-mentions.ts b/webview-ui/src/utils/context-mentions.ts index 22dba8864f..aee441bf02 100644 --- a/webview-ui/src/utils/context-mentions.ts +++ b/webview-ui/src/utils/context-mentions.ts @@ -108,6 +108,25 @@ export enum ContextMenuOptionType { Mode = "mode", // Add mode type Command = "command", // Add command type SectionHeader = "sectionHeader", // Add section header type + History = "history", // Recall a previously sent user prompt +} + +/** + * "!" (and its full-width form "!") at the very start of the input opens the + * prompt history picker. It must not contain whitespace, so the menu dismisses + * itself as soon as the user starts writing a real message. + * + * This is deliberately anchored to the start of the input: "!" is a common + * character in ordinary prose and code ("Great!", "if (!x)", "![alt](url)"), + * so triggering on any occurrence would hijack Enter for those messages. + */ +export function isHistoryTrigger(text: string): boolean { + // "![alt](url)" is a markdown image at the start of a message, not a picker. + if (text.startsWith("![")) { + return false + } + + return /^[!!]\S*$/.test(text) } export interface ContextMenuQueryItem { @@ -128,7 +147,27 @@ export function getContextMenuOptions( dynamicSearchResults: SearchResult[] = [], modes?: ModeConfig[], commands?: Command[], + history: string[] = [], ): ContextMenuQueryItem[] { + // Prompt history recall. Newest-first, de-duplicated so that repeated + // prompts (e.g. "continue") don't fill the picker with identical rows. + if (isHistoryTrigger(query)) { + const historyQuery = query.slice(1) + const prompts = Array.from(new Set(history.filter((prompt) => prompt.trim().length > 0))) + + if (prompts.length === 0) { + return [{ type: ContextMenuOptionType.NoResults }] + } + + const searchable = prompts.map((prompt) => ({ prompt })) + const fzf = new Fzf(searchable, { selector: (item) => item.prompt }) + const matching = historyQuery ? fzf.find(historyQuery).map((result) => result.item.prompt) : prompts + + return matching.length > 0 + ? matching.map((prompt) => ({ type: ContextMenuOptionType.History, value: prompt })) + : [{ type: ContextMenuOptionType.NoResults }] + } + // Handle slash commands for modes and commands // Only process as slash command if the query itself starts with "/" (meaning we're typing a slash command) if (query.startsWith("/")) { @@ -367,6 +406,11 @@ export function getContextMenuOptions( export function shouldShowContextMenu(text: string, position: number): boolean { const beforeCursor = text.slice(0, position) + // Check for prompt history recall ("!" / "!" at the start of the input) + if (isHistoryTrigger(text)) { + return true + } + // Check if we're in a slash command context (at the beginning and no space yet) if (text.startsWith("/") && !text.includes(" ") && position <= text.length) { return true From 9222cbd5b55f2c2abe5844d644061ac5ec01893c Mon Sep 17 00:00:00 2001 From: Yarco Wang Date: Sat, 24 Oct 2026 21:50:23 +0800 Subject: [PATCH 2/3] fix(chat): harden prompt history picker edge cases Escape now closes the picker before it can cancel an edit, so the draft is kept. Enter still sends the message when no prompt matches the query instead of being swallowed. Fuzzy matches keep newest-first order instead of fzf's ranking. Add component tests for the Escape precedence and the no-match send path, plus a gallery story with picker-open snapshots. --- webview-ui/playwright/gallery/stories.tsx | 4 ++ .../src/components/chat/ChatTextArea.tsx | 20 ++++++++-- .../chat/__tests__/ChatTextArea.spec.tsx | 38 ++++++++++++++++++ .../__tests__/ChatTextArea.visual.fixture.tsx | 39 +++++++++++++++++++ .../chat/__tests__/ChatTextArea.visual.tsx | 18 +++++++++ .../utils/__tests__/context-mentions.spec.ts | 11 ++++++ webview-ui/src/utils/context-mentions.ts | 13 ++++++- 7 files changed, 137 insertions(+), 6 deletions(-) diff --git a/webview-ui/playwright/gallery/stories.tsx b/webview-ui/playwright/gallery/stories.tsx index 90be332890..d7df34eb2f 100644 --- a/webview-ui/playwright/gallery/stories.tsx +++ b/webview-ui/playwright/gallery/stories.tsx @@ -155,6 +155,10 @@ export const stories: Record = { const { ChatTextAreaStory } = await import("@/components/chat/__tests__/ChatTextArea.visual.fixture") return }, + "chat-text-area-history": async () => { + const { ChatTextAreaHistoryStory } = await import("@/components/chat/__tests__/ChatTextArea.visual.fixture") + return + }, "history-empty": async () => { const [{ AppProviders }, { default: HistoryView }] = await Promise.all([ import("../AppProviders"), diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index cccf60da3a..ec1a25b1b4 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -503,7 +503,6 @@ export const ChatTextArea = forwardRef( return } if ((event.key === "Enter" || event.key === "Tab") && selectedMenuIndex !== -1) { - event.preventDefault() const selectedOption = getContextMenuOptions( searchQuery, selectedType, @@ -519,9 +518,14 @@ export const ChatTextArea = forwardRef( selectedOption.type !== ContextMenuOptionType.NoResults && selectedOption.type !== ContextMenuOptionType.SectionHeader ) { + event.preventDefault() handleMentionSelect(selectedOption.type, selectedOption.value) + return } - return + + // Nothing selectable (e.g. "No results"). Do not swallow the + // key: fall through so Enter still sends the message instead + // of leaving the composer unresponsive. } } @@ -1144,8 +1148,16 @@ export const ChatTextArea = forwardRef( }} onFocus={() => setIsFocused(true)} onKeyDown={(e) => { - // Handle ESC to cancel in edit mode - if (isEditMode && e.key === "Escape" && !e.nativeEvent?.isComposing) { + // Handle ESC to cancel in edit mode. The context menu + // takes precedence: while the history picker is open, + // ESC only closes it, so cancelling the edit (which + // discards the draft) needs a second press. + if ( + isEditMode && + e.key === "Escape" && + !showContextMenu && + !e.nativeEvent?.isComposing + ) { e.preventDefault() onCancel?.() return diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx index 0d8583e676..d61e0a10f5 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx @@ -680,6 +680,44 @@ describe("ChatTextArea", () => { expect(container.textContent).not.toContain("Third prompt") }) + it("should close the picker before cancelling an edit on Escape", () => { + const onCancel = vi.fn() + const { container } = render( + , + ) + + const textarea = container.querySelector("textarea")! + + fireEvent.change(textarea, { target: { value: "!", selectionStart: 1 } }) + expect(container.textContent).toContain("Third prompt") + + // First press closes the picker and keeps the edit (and its draft). + fireEvent.keyDown(textarea, { key: "Escape" }) + expect(onCancel).not.toHaveBeenCalled() + expect(container.textContent).not.toContain("Third prompt") + + // Second press, with no picker open, cancels the edit. + fireEvent.keyDown(textarea, { key: "Escape" }) + expect(onCancel).toHaveBeenCalledTimes(1) + }) + + it("should still send on Enter when the history query matches nothing", () => { + const onSend = vi.fn() + const setInputValue = vi.fn() + const { container } = render( + , + ) + + const textarea = container.querySelector("textarea")! + + fireEvent.change(textarea, { target: { value: "!zzz", selectionStart: 4 } }) + fireEvent.keyDown(textarea, { key: "Enter" }) + + // "No results" is not selectable, so Enter must not be swallowed. + expect(onSend).toHaveBeenCalledTimes(1) + expect(setInputValue).not.toHaveBeenCalledWith("Third prompt") + }) + it("should reset history navigation when sending message", () => { const onSend = vi.fn() const setInputValue = vi.fn() diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.fixture.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.fixture.tsx index 7585881f14..480ee58362 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.fixture.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.fixture.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react" import { defaultModeSlug, type Mode } from "@roo/modes" +import type { ClineMessage } from "@roo-code/types" import { AppProviders } from "../../../../playwright/AppProviders" import { ChatTextArea } from "../ChatTextArea" @@ -33,3 +34,41 @@ export function ChatTextAreaStory() { ) } + +// Prompt history is derived from the current task's user messages, so the +// picker needs a non-empty conversation. The extra top padding keeps the +// popover, which opens upward from the composer, inside the screenshot bounds. +const historyMessages: ClineMessage[] = [ + { ts: 1, type: "say", say: "user_feedback", text: "Add a retry guard to the upload test" }, + { ts: 2, type: "say", say: "user_feedback", text: "Explain the diff for the parser change" }, +] + +export function ChatTextAreaHistoryStory() { + const [inputValue, setInputValue] = useState("") + const [selectedImages, setSelectedImages] = useState([]) + const [mode, setMode] = useState(defaultModeSlug) + + return ( + +
+ undefined} + onSelectImages={() => undefined} + shouldDisableImages={false} + mode={mode} + setMode={setMode} + modeShortcutText="Ctrl+. for next mode" + /> +
+
+ ) +} diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.tsx index 69ad3e675c..55efb4885f 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.visual.tsx @@ -22,4 +22,22 @@ for (const theme of visualThemes) { focusedControl: editor, }) }) + + test(`renders the prompt history picker in the VS Code ${theme.name} theme`, async ({ mount, page }) => { + const component = mountedStory(await mount("chat-text-area-history")) + await applyVisualTheme(page, theme) + // The full provider bundle leaves a bare Zod reference after gallery tree-shaking. + await page.evaluate(() => Object.assign(globalThis, { z: undefined })) + const story = component.getByTestId("chat-text-area-story") + const editor = story.getByRole("textbox") + await expect(editor).toBeVisible() + + // A leading "!" opens the picker. The newest prompt is listed first. + await editor.click() + await editor.pressSequentially("!") + await expect(story.getByText("Explain the diff for the parser change")).toBeVisible() + await expect(story.getByText("Add a retry guard to the upload test")).toBeVisible() + + await expect(story).toHaveScreenshot(`chat-composer-history-${theme.name}.png`) + }) } diff --git a/webview-ui/src/utils/__tests__/context-mentions.spec.ts b/webview-ui/src/utils/__tests__/context-mentions.spec.ts index 4b716d83f0..182867e7fa 100644 --- a/webview-ui/src/utils/__tests__/context-mentions.spec.ts +++ b/webview-ui/src/utils/__tests__/context-mentions.spec.ts @@ -630,6 +630,17 @@ describe("getContextMenuOptions for prompt history", () => { expect(options[0]).toMatchObject({ type: ContextMenuOptionType.History, value: "Third prompt" }) }) + it("should keep newest-first order when fuzzy scores rank matches differently", () => { + // fzf scores the exact "fix" (older, index 1) above the scattered + // "finally, invest in x-rays" (newer, index 0). The picker must still + // list the newer prompt first. + const options = getContextMenuOptions("!fix", null, [], [], undefined, undefined, [ + "finally, invest in x-rays", + "fix", + ]) + expect(options.map((option) => option.value)).toEqual(["finally, invest in x-rays", "fix"]) + }) + it("should drop duplicate prompts so the picker has no identical rows", () => { const options = getContextMenuOptions("!", null, [], [], undefined, undefined, ["继续", "explain this", "继续"]) expect(options.map((option) => option.value)).toEqual(["继续", "explain this"]) diff --git a/webview-ui/src/utils/context-mentions.ts b/webview-ui/src/utils/context-mentions.ts index aee441bf02..6cb8798352 100644 --- a/webview-ui/src/utils/context-mentions.ts +++ b/webview-ui/src/utils/context-mentions.ts @@ -159,9 +159,18 @@ export function getContextMenuOptions( return [{ type: ContextMenuOptionType.NoResults }] } - const searchable = prompts.map((prompt) => ({ prompt })) + // fzf ranks matches by score, which would put an older prompt above a + // newer one. The picker promises newest-first history, so keep the + // original (input) order of the prompts that matched. + const searchable = prompts.map((prompt, index) => ({ prompt, index })) const fzf = new Fzf(searchable, { selector: (item) => item.prompt }) - const matching = historyQuery ? fzf.find(historyQuery).map((result) => result.item.prompt) : prompts + const matching = historyQuery + ? fzf + .find(historyQuery) + .map((result) => result.item) + .sort((a, b) => a.index - b.index) + .map((item) => item.prompt) + : prompts return matching.length > 0 ? matching.map((prompt) => ({ type: ContextMenuOptionType.History, value: prompt })) From 22aeee968bbc7f6cdcc92db35cc5621487419e84 Mon Sep 17 00:00:00 2001 From: Yarco Wang Date: Sat, 24 Oct 2026 22:34:18 +0800 Subject: [PATCH 3/3] test(visual): add picker snapshots and refresh the electron chat baseline --- .../electron-chat-dark-sidebar.png | Bin 29896 -> 30493 bytes .../chat-composer-history-dark.png | Bin 0 -> 13829 bytes ...t-composer-history-high-contrast-light.png | Bin 0 -> 14447 bytes .../chat-composer-history-high-contrast.png | Bin 0 -> 13542 bytes .../chat-composer-history-light.png | Bin 0 -> 13658 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-light.png diff --git a/apps/vscode-e2e/src/visual/__screenshots__/electron-chat-dark-sidebar.png b/apps/vscode-e2e/src/visual/__screenshots__/electron-chat-dark-sidebar.png index 3791a71175cfa767cb683a6453d6c2e0bebf05c0..0fbd8ef748ac8c56452e0e6343c63aa04faf5154 100644 GIT binary patch delta 10991 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 bdqHF#blkAdi?)Pc0xvb?`${E>=D7a>oZmZG diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..8b273d71b96cb2024a01f5fe39b88ea0daa1ef16 GIT binary patch literal 13829 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast-light.png new file mode 100644 index 0000000000000000000000000000000000000000..110a0788b463c3658c7123615c851bd6506772ff GIT binary patch literal 14447 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-high-contrast.png new file mode 100644 index 0000000000000000000000000000000000000000..3330e4413c1b9785d3e23e2a8a2ad08485983934 GIT binary patch literal 13542 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-history-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c57d5c28af5f9e7af1a03ae3987a8035f58f47e8 GIT binary patch literal 13658 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 vCka_`W*M->cvEY}Pp1 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