mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
Move summarize button inside of context view (#4015)
This commit is contained in:
@@ -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';
|
||||
@@ -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';
|
||||
@@ -110,7 +109,7 @@ export default function ChatInput({
|
||||
const { alerts, addAlert, clearAlerts } = useAlerts();
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const toolCount = useToolCount();
|
||||
const { isLoadingCompaction } = useChatContextManager();
|
||||
const { isLoadingCompaction, handleManualCompaction } = useChatContextManager();
|
||||
const { getProviders, read } = useConfig();
|
||||
const { getCurrentModelAndProvider, currentModel, currentProvider } = useModelAndProvider();
|
||||
const [tokenLimit, setTokenLimit] = useState<number>(TOKEN_LIMIT_DEFAULT);
|
||||
@@ -420,7 +419,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 +427,11 @@ export default function ChatInput({
|
||||
current: numTokens,
|
||||
total: tokenLimit,
|
||||
},
|
||||
showSummarizeButton: true,
|
||||
onSummarize: () => {
|
||||
handleManualCompaction(messages, setMessages);
|
||||
},
|
||||
summarizeIcon: <ScrollText size={12} />,
|
||||
});
|
||||
}
|
||||
} else if (isTokenLimitLoaded && tokenLimit) {
|
||||
@@ -439,6 +443,14 @@ export default function ChatInput({
|
||||
current: 0,
|
||||
total: tokenLimit,
|
||||
},
|
||||
showSummarizeButton: messages.length > 0,
|
||||
onSummarize:
|
||||
messages.length > 0
|
||||
? () => {
|
||||
handleManualCompaction(messages, setMessages);
|
||||
}
|
||||
: undefined,
|
||||
summarizeIcon: messages.length > 0 ? <ScrollText size={12} /> : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1286,13 +1298,6 @@ export default function ChatInput({
|
||||
</Tooltip>
|
||||
<div className="w-px h-4 bg-border-default mx-2" />
|
||||
<BottomMenuModeSelection />
|
||||
{messages.length > 0 && (
|
||||
<ManualCompactButton
|
||||
messages={messages}
|
||||
isLoading={isLoading}
|
||||
setMessages={setMessages}
|
||||
/>
|
||||
)}
|
||||
<div className="w-px h-4 bg-border-default mx-2" />
|
||||
<div className="flex items-center h-full">
|
||||
<Tooltip>
|
||||
|
||||
@@ -60,6 +60,19 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => {
|
||||
: alert.progress!.total}
|
||||
</span>
|
||||
</div>
|
||||
{alert.showSummarizeButton && alert.onSummarize && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
alert.onSummarize!();
|
||||
}}
|
||||
className="flex items-center gap-1.5 text-[11px] hover:opacity-80 cursor-pointer outline-none mt-1"
|
||||
>
|
||||
{alert.summarizeIcon}
|
||||
<span>Summarize now</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -16,4 +16,7 @@ export interface Alert {
|
||||
current: number;
|
||||
total: number;
|
||||
};
|
||||
showSummarizeButton?: boolean;
|
||||
onSummarize?: () => void;
|
||||
summarizeIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
@@ -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<boolean>(false);
|
||||
const [errorLoadingSummary, setErrorLoadingSummary] = useState<boolean>(false);
|
||||
const [preparingManualSummary, setPreparingManualSummary] = useState<boolean>(false);
|
||||
const [isConfirmationOpen, setIsConfirmationOpen] = useState<boolean>(false);
|
||||
const [pendingCompactionData, setPendingCompactionData] = useState<{
|
||||
messages: Message[];
|
||||
setMessages: (messages: Message[]) => void;
|
||||
} | null>(null);
|
||||
|
||||
const handleContextLengthExceeded = async (messages: Message[]): Promise<void> => {
|
||||
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,14 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }>
|
||||
|
||||
// add the message to the message thread
|
||||
setMessages([...messages, summarizationRequest]);
|
||||
|
||||
setIsConfirmationOpen(false);
|
||||
setPendingCompactionData(null);
|
||||
};
|
||||
|
||||
const handleCompactionCancel = () => {
|
||||
setIsConfirmationOpen(false);
|
||||
setPendingCompactionData(null);
|
||||
};
|
||||
|
||||
const updateSummary = (newSummaryContent: string) => {
|
||||
@@ -242,6 +277,8 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }>
|
||||
isLoadingCompaction,
|
||||
errorLoadingSummary,
|
||||
preparingManualSummary,
|
||||
isConfirmationOpen,
|
||||
pendingCompactionData,
|
||||
|
||||
// Actions
|
||||
updateSummary,
|
||||
@@ -259,6 +296,39 @@ export const ChatContextManagerProvider: React.FC<{ children: React.ReactNode }>
|
||||
return (
|
||||
<ChatContextManagerContext.Provider value={value}>
|
||||
{children}
|
||||
|
||||
{/* Confirmation Modal */}
|
||||
<Dialog open={isConfirmationOpen} onOpenChange={handleCompactionCancel}>
|
||||
<DialogContent className="sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<ScrollText className="text-iconStandard" size={24} />
|
||||
Compact Conversation
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
This will compact your conversation by summarizing the context into a single message
|
||||
and will help you save context space for future interactions.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="py-4">
|
||||
<p className="text-textStandard">
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="pt-2">
|
||||
<Button type="button" variant="outline" onClick={handleCompactionCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="button" onClick={handleCompactionConfirm}>
|
||||
Compact Conversation
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</ChatContextManagerContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ export const ManualCompactButton: React.FC<ManualCompactButtonProps> = ({
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* Confirmation Modal */}
|
||||
{/* Summarization Confirmation Modal */}
|
||||
<Dialog open={isConfirmationOpen} onOpenChange={handleClose}>
|
||||
<DialogContent className="sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
|
||||
Reference in New Issue
Block a user