From ec9268de64ebcbb9b46597e22a723e870885c6ea Mon Sep 17 00:00:00 2001 From: David Katz Date: Mon, 11 Aug 2025 16:45:31 -0400 Subject: [PATCH 1/5] move summarize button --- ui/desktop/src/components/ChatInput.tsx | 21 ++++++++++++++++--- ui/desktop/src/components/alerts/AlertBox.tsx | 14 +++++++++++++ ui/desktop/src/components/alerts/types.ts | 3 +++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index 145074c7717d..fa4f4bde6aca 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -1,5 +1,5 @@ import React, { useRef, useState, useEffect, useMemo } from 'react'; -import { FolderKey } from 'lucide-react'; +import { FolderKey, ScrollText } from 'lucide-react'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/Tooltip'; import { Button } from './ui/button'; import type { View } from '../App'; @@ -110,7 +110,7 @@ export default function ChatInput({ const { alerts, addAlert, clearAlerts } = useAlerts(); const dropdownRef = useRef(null); const toolCount = useToolCount(); - const { isLoadingCompaction } = useChatContextManager(); + const { isLoadingCompaction, handleManualCompaction } = useChatContextManager(); const { getProviders, read } = useConfig(); const { getCurrentModelAndProvider, currentModel, currentProvider } = useModelAndProvider(); const [tokenLimit, setTokenLimit] = useState(TOKEN_LIMIT_DEFAULT); @@ -420,7 +420,7 @@ export default function ChatInput({ autoShow: true, // Auto-show token limit warnings }); } else { - // Show info alert only when not in warning/error state + // Show info alert with summarize button addAlert({ type: AlertType.Info, message: 'Context window', @@ -428,6 +428,12 @@ export default function ChatInput({ current: numTokens, total: tokenLimit, }, + showSummarizeButton: true, + onSummarize: () => { + // Trigger manual compaction + handleManualCompaction(messages, setMessages); + }, + summarizeIcon: , }); } } else if (isTokenLimitLoaded && tokenLimit) { @@ -439,6 +445,15 @@ export default function ChatInput({ current: 0, total: tokenLimit, }, + showSummarizeButton: messages.length > 0, + onSummarize: + messages.length > 0 + ? () => { + // Trigger manual compaction + handleManualCompaction(messages, setMessages); + } + : undefined, + summarizeIcon: messages.length > 0 ? : undefined, }); } diff --git a/ui/desktop/src/components/alerts/AlertBox.tsx b/ui/desktop/src/components/alerts/AlertBox.tsx index c93f249f2ff5..0cb67d9fc813 100644 --- a/ui/desktop/src/components/alerts/AlertBox.tsx +++ b/ui/desktop/src/components/alerts/AlertBox.tsx @@ -60,6 +60,20 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => { : alert.progress!.total} + {/* Add summarize button for context window alerts */} + {alert.showSummarizeButton && alert.onSummarize && ( + + )} ) : ( <> diff --git a/ui/desktop/src/components/alerts/types.ts b/ui/desktop/src/components/alerts/types.ts index 661191e50b7f..44eeafbd19a0 100644 --- a/ui/desktop/src/components/alerts/types.ts +++ b/ui/desktop/src/components/alerts/types.ts @@ -16,4 +16,7 @@ export interface Alert { current: number; total: number; }; + showSummarizeButton?: boolean; + onSummarize?: () => void; + summarizeIcon?: React.ReactNode; } From a6c1323d832130e1a3c27003b2d7f5b28172ae28 Mon Sep 17 00:00:00 2001 From: David Katz Date: Mon, 11 Aug 2025 17:49:32 -0400 Subject: [PATCH 2/5] rm old button --- ui/desktop/src/components/ChatInput.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index fa4f4bde6aca..de45c95e8356 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -12,7 +12,6 @@ import { Message } from '../types/message'; import { DirSwitcher } from './bottom_menu/DirSwitcher'; import ModelsBottomBar from './settings/models/bottom_bar/ModelsBottomBar'; import { BottomMenuModeSelection } from './bottom_menu/BottomMenuModeSelection'; -import { ManualCompactButton } from './context_management/ManualCompactButton'; import { AlertType, useAlerts } from './alerts'; import { useToolCount } from './alerts/useToolCount'; import { useConfig } from './ConfigContext'; @@ -1301,13 +1300,6 @@ export default function ChatInput({
- {messages.length > 0 && ( - - )}
From fc7f7256ea87847035d9f140f00681cafee0d3f3 Mon Sep 17 00:00:00 2001 From: David Katz Date: Mon, 11 Aug 2025 18:18:13 -0400 Subject: [PATCH 3/5] dialog parity --- .../context_management/ChatContextManager.tsx | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/ui/desktop/src/components/context_management/ChatContextManager.tsx b/ui/desktop/src/components/context_management/ChatContextManager.tsx index 2e18e02bf354..1af7be1b20ab 100644 --- a/ui/desktop/src/components/context_management/ChatContextManager.tsx +++ b/ui/desktop/src/components/context_management/ChatContextManager.tsx @@ -1,10 +1,20 @@ import React, { createContext, useContext, useState } from 'react'; +import { ScrollText } from 'lucide-react'; import { Message } from '../../types/message'; import { manageContextFromBackend, convertApiMessageToFrontendMessage, createSummarizationRequestMessage, } from './index'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '../ui/dialog'; +import { Button } from '../ui/button'; // Define the context management interface interface ChatContextManagerState { @@ -14,6 +24,8 @@ interface ChatContextManagerState { isLoadingCompaction: boolean; errorLoadingSummary: boolean; preparingManualSummary: boolean; + isConfirmationOpen: boolean; + pendingCompactionData: { messages: Message[]; setMessages: (messages: Message[]) => void } | null; } interface ChatContextManagerActions { @@ -50,6 +62,11 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }> const [isLoadingCompaction, setIsLoadingCompaction] = useState(false); const [errorLoadingSummary, setErrorLoadingSummary] = useState(false); const [preparingManualSummary, setPreparingManualSummary] = useState(false); + const [isConfirmationOpen, setIsConfirmationOpen] = useState(false); + const [pendingCompactionData, setPendingCompactionData] = useState<{ + messages: Message[]; + setMessages: (messages: Message[]) => void; + } | null>(null); const handleContextLengthExceeded = async (messages: Message[]): Promise => { setIsLoadingCompaction(true); @@ -90,6 +107,16 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }> messages: Message[], setMessages: (messages: Message[]) => void ): void => { + // Store the pending compaction data and open confirmation dialog + setPendingCompactionData({ messages, setMessages }); + setIsConfirmationOpen(true); + }; + + const handleCompactionConfirm = () => { + if (!pendingCompactionData) return; + + const { messages, setMessages } = pendingCompactionData; + // add some messages to the message thread // these messages will be filtered out in chat view // but they will also be what allows us to render some text in the chatview itself, similar to CLE events @@ -100,6 +127,15 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }> // add the message to the message thread setMessages([...messages, summarizationRequest]); + + // Close dialog and clear pending data + setIsConfirmationOpen(false); + setPendingCompactionData(null); + }; + + const handleCompactionCancel = () => { + setIsConfirmationOpen(false); + setPendingCompactionData(null); }; const updateSummary = (newSummaryContent: string) => { @@ -242,6 +278,8 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }> isLoadingCompaction, errorLoadingSummary, preparingManualSummary, + isConfirmationOpen, + pendingCompactionData, // Actions updateSummary, @@ -259,6 +297,39 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }> return ( {children} + + {/* Confirmation Modal */} + + + + + + Compact Conversation + + + This will compact your conversation by summarizing the context into a single message + and will help you save context space for future interactions. + + + +
+

+ Previous messages will remain visible but only the summary will be included in the + active context for Goose. This is useful for long conversations that are approaching + the context limit. +

+
+ + + + + +
+
); }; From 80aa56cfae2836c5280c700a3abf9244ab3806da Mon Sep 17 00:00:00 2001 From: David Katz Date: Mon, 11 Aug 2025 18:21:36 -0400 Subject: [PATCH 4/5] Update summarization button text to lowercase 'Summarize now' --- ui/desktop/src/components/alerts/AlertBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/desktop/src/components/alerts/AlertBox.tsx b/ui/desktop/src/components/alerts/AlertBox.tsx index 0cb67d9fc813..7af81454931e 100644 --- a/ui/desktop/src/components/alerts/AlertBox.tsx +++ b/ui/desktop/src/components/alerts/AlertBox.tsx @@ -71,7 +71,7 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => { className="flex items-center gap-1.5 text-[11px] hover:opacity-80 cursor-pointer outline-none mt-1" > {alert.summarizeIcon} - Summarize Now + Summarize now )}
From 097545352a419a61a761602e5c2d59cab81648d0 Mon Sep 17 00:00:00 2001 From: David Katz Date: Mon, 11 Aug 2025 18:25:16 -0400 Subject: [PATCH 5/5] better comments --- ui/desktop/src/components/ChatInput.tsx | 2 -- ui/desktop/src/components/alerts/AlertBox.tsx | 1 - .../src/components/context_management/ChatContextManager.tsx | 1 - .../src/components/context_management/ManualCompactButton.tsx | 2 +- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index de45c95e8356..bf7c387d3e77 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -429,7 +429,6 @@ export default function ChatInput({ }, showSummarizeButton: true, onSummarize: () => { - // Trigger manual compaction handleManualCompaction(messages, setMessages); }, summarizeIcon: , @@ -448,7 +447,6 @@ export default function ChatInput({ onSummarize: messages.length > 0 ? () => { - // Trigger manual compaction handleManualCompaction(messages, setMessages); } : undefined, diff --git a/ui/desktop/src/components/alerts/AlertBox.tsx b/ui/desktop/src/components/alerts/AlertBox.tsx index 7af81454931e..0fafdd3bb531 100644 --- a/ui/desktop/src/components/alerts/AlertBox.tsx +++ b/ui/desktop/src/components/alerts/AlertBox.tsx @@ -60,7 +60,6 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => { : alert.progress!.total}
- {/* Add summarize button for context window alerts */} {alert.showSummarizeButton && alert.onSummarize && (
- {/* Confirmation Modal */} + {/* Summarization Confirmation Modal */}