Merge pull request #5542 from menloresearch/fix/increase-context-window-could-not-popup

This commit is contained in:
Louis 2025-06-26 03:22:22 -07:00 committed by GitHub
commit 0af271b05f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 133 additions and 133 deletions

View File

@ -35,7 +35,6 @@ import { ModelLoader } from '@/containers/loaders/ModelLoader'
import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable' import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable'
import { getConnectedServers } from '@/services/mcp' import { getConnectedServers } from '@/services/mcp'
import { stopAllModels } from '@/services/models' import { stopAllModels } from '@/services/models'
import { useOutOfContextPromiseModal } from './dialogs/OutOfContextDialog'
type ChatInputProps = { type ChatInputProps = {
className?: string className?: string
@ -55,8 +54,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const { spellCheckChatInput } = useGeneralSetting() const { spellCheckChatInput } = useGeneralSetting()
const { showModal, PromiseModal: OutOfContextModal } =
useOutOfContextPromiseModal()
const maxRows = 10 const maxRows = 10
const { selectedModel } = useModelProvider() const { selectedModel } = useModelProvider()
@ -107,7 +104,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
return return
} }
setMessage('') setMessage('')
sendMessage(prompt, showModal) sendMessage(prompt)
} }
useEffect(() => { useEffect(() => {
@ -599,7 +596,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
</div> </div>
</div> </div>
)} )}
<OutOfContextModal />
</div> </div>
) )
} }

View File

@ -83,7 +83,6 @@ export const ThreadContent = memo(
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
streamTools?: any streamTools?: any
contextOverflowModal?: React.ReactNode | null contextOverflowModal?: React.ReactNode | null
showContextOverflowModal?: () => Promise<unknown>
} }
) => { ) => {
const [message, setMessage] = useState(item.content?.[0]?.text?.value || '') const [message, setMessage] = useState(item.content?.[0]?.text?.value || '')
@ -134,10 +133,7 @@ export const ThreadContent = memo(
} }
if (toSendMessage) { if (toSendMessage) {
deleteMessage(toSendMessage.thread_id, toSendMessage.id ?? '') deleteMessage(toSendMessage.thread_id, toSendMessage.id ?? '')
sendMessage( sendMessage(toSendMessage.content?.[0]?.text?.value || '')
toSendMessage.content?.[0]?.text?.value || '',
item.showContextOverflowModal
)
} }
}, [deleteMessage, getMessages, item, sendMessage]) }, [deleteMessage, getMessages, item, sendMessage])
@ -179,16 +175,9 @@ export const ThreadContent = memo(
deleteMessage(threadMessages[i].thread_id, threadMessages[i].id) deleteMessage(threadMessages[i].thread_id, threadMessages[i].id)
} }
sendMessage(message, item.showContextOverflowModal) sendMessage(message)
}, },
[ [deleteMessage, getMessages, item.thread_id, message, sendMessage]
deleteMessage,
getMessages,
item.thread_id,
message,
sendMessage,
item.showContextOverflowModal,
]
) )
const isToolCalls = const isToolCalls =

View File

@ -8,61 +8,33 @@ import {
DialogTitle, DialogTitle,
} from '@/components/ui/dialog' } from '@/components/ui/dialog'
import { ReactNode, useCallback, useState } from 'react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { useContextSizeApproval } from '@/hooks/useModelContextApproval'
export function useOutOfContextPromiseModal() { export default function OutOfContextPromiseModal() {
const [isOpen, setIsOpen] = useState(false) const { isModalOpen, modalProps, setModalOpen } = useContextSizeApproval()
const [modalProps, setModalProps] = useState<{ if (!modalProps) {
resolveRef:
| ((value: 'ctx_len' | 'context_shift' | undefined) => void)
| null
}>({
resolveRef: null,
})
// Function to open the modal and return a Promise
const showModal = useCallback(() => {
return new Promise((resolve) => {
setModalProps({
resolveRef: resolve,
})
setIsOpen(true)
})
}, [])
const PromiseModal = useCallback((): ReactNode => {
if (!isOpen) {
return null return null
} }
const { onApprove, onDeny } = modalProps
const handleContextLength = () => { const handleContextLength = () => {
setIsOpen(false) onApprove('ctx_len')
if (modalProps.resolveRef) {
modalProps.resolveRef('ctx_len')
}
} }
const handleContextShift = () => { const handleContextShift = () => {
setIsOpen(false) onApprove('context_shift')
if (modalProps.resolveRef) {
modalProps.resolveRef('context_shift')
} }
}
const handleCancel = () => { const handleDialogOpen = (open: boolean) => {
setIsOpen(false) setModalOpen(open)
if (modalProps.resolveRef) { if (!open) {
modalProps.resolveRef(undefined) onDeny()
} }
} }
return ( return (
<Dialog <Dialog open={isModalOpen} onOpenChange={handleDialogOpen}>
open={isOpen}
onOpenChange={(open) => {
setIsOpen(open)
if (!open) handleCancel()
}}
>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
@ -87,7 +59,6 @@ export function useOutOfContextPromiseModal() {
className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4" className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4"
onClick={() => { onClick={() => {
handleContextShift() handleContextShift()
setIsOpen(false)
}} }}
> >
{t('outOfContextError.truncateInput', 'Truncate Input')} {t('outOfContextError.truncateInput', 'Truncate Input')}
@ -96,7 +67,6 @@ export function useOutOfContextPromiseModal() {
asChild asChild
onClick={() => { onClick={() => {
handleContextLength() handleContextLength()
setIsOpen(false)
}} }}
> >
<span className="text-main-view-fg/70"> <span className="text-main-view-fg/70">
@ -110,6 +80,4 @@ export function useOutOfContextPromiseModal() {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
) )
}, [isOpen, modalProps])
return { showModal, PromiseModal }
} }

View File

@ -30,6 +30,7 @@ import { useToolApproval } from '@/hooks/useToolApproval'
import { useToolAvailable } from '@/hooks/useToolAvailable' import { useToolAvailable } from '@/hooks/useToolAvailable'
import { OUT_OF_CONTEXT_SIZE } from '@/utils/error' import { OUT_OF_CONTEXT_SIZE } from '@/utils/error'
import { updateSettings } from '@/services/providers' import { updateSettings } from '@/services/providers'
import { useContextSizeApproval } from './useModelContextApproval'
export const useChat = () => { export const useChat = () => {
const { prompt, setPrompt } = usePrompt() const { prompt, setPrompt } = usePrompt()
@ -47,6 +48,8 @@ export const useChat = () => {
const { approvedTools, showApprovalModal, allowAllMCPPermissions } = const { approvedTools, showApprovalModal, allowAllMCPPermissions } =
useToolApproval() useToolApproval()
const { showApprovalModal: showIncreaseContextSizeModal } =
useContextSizeApproval()
const { getDisabledToolsForThread } = useToolAvailable() const { getDisabledToolsForThread } = useToolAvailable()
const { getProviderByName, selectedModel, selectedProvider } = const { getProviderByName, selectedModel, selectedProvider } =
@ -223,11 +226,7 @@ export const useChat = () => {
) )
const sendMessage = useCallback( const sendMessage = useCallback(
async ( async (message: string, troubleshooting = true) => {
message: string,
showModal?: () => Promise<unknown>,
troubleshooting = true
) => {
const activeThread = await getCurrentThread() const activeThread = await getCurrentThread()
resetTokenSpeed() resetTokenSpeed()
@ -361,7 +360,7 @@ export const useChat = () => {
selectedModel && selectedModel &&
troubleshooting troubleshooting
) { ) {
const method = await showModal?.() const method = await showIncreaseContextSizeModal()
if (method === 'ctx_len') { if (method === 'ctx_len') {
/// Increase context size /// Increase context size
activeProvider = await increaseModelContextSize( activeProvider = await increaseModelContextSize(
@ -447,8 +446,7 @@ export const useChat = () => {
updateThreadTimestamp, updateThreadTimestamp,
setPrompt, setPrompt,
selectedModel, selectedModel,
currentAssistant?.instructions, currentAssistant,
currentAssistant.parameters,
tools, tools,
updateLoadingModel, updateLoadingModel,
getDisabledToolsForThread, getDisabledToolsForThread,
@ -456,6 +454,7 @@ export const useChat = () => {
allowAllMCPPermissions, allowAllMCPPermissions,
showApprovalModal, showApprovalModal,
updateTokenSpeed, updateTokenSpeed,
showIncreaseContextSizeModal,
increaseModelContextSize, increaseModelContextSize,
toggleOnContextShifting, toggleOnContextShifting,
] ]

View File

@ -0,0 +1,53 @@
import { create } from 'zustand'
export type ApprovalModalProps = {
onApprove: (method: 'ctx_len' | 'context_shift') => void
onDeny: () => void
}
type ApprovalState = {
// Modal state
isModalOpen: boolean
modalProps: ApprovalModalProps | null
showApprovalModal: () => Promise<'ctx_len' | 'context_shift' | undefined>
closeModal: () => void
setModalOpen: (open: boolean) => void
}
export const useContextSizeApproval = create<ApprovalState>()((set, get) => ({
isModalOpen: false,
modalProps: null,
showApprovalModal: async () => {
return new Promise<'ctx_len' | 'context_shift' | undefined>((resolve) => {
set({
isModalOpen: true,
modalProps: {
onApprove: (method) => {
get().closeModal()
resolve(method)
},
onDeny: () => {
get().closeModal()
resolve(undefined)
},
},
})
})
},
closeModal: () => {
set({
isModalOpen: false,
modalProps: null,
})
},
setModalOpen: (open: boolean) => {
set({ isModalOpen: open })
if (!open) {
get().closeModal()
}
},
}))

View File

@ -18,6 +18,7 @@ import { AnalyticProvider } from '@/providers/AnalyticProvider'
import { useLeftPanel } from '@/hooks/useLeftPanel' import { useLeftPanel } from '@/hooks/useLeftPanel'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import ToolApproval from '@/containers/dialogs/ToolApproval' import ToolApproval from '@/containers/dialogs/ToolApproval'
import OutOfContextPromiseModal from '@/containers/dialogs/OutOfContextDialog'
export const Route = createRootRoute({ export const Route = createRootRoute({
component: RootLayout, component: RootLayout,
@ -94,6 +95,7 @@ function RootLayout() {
{/* <TanStackRouterDevtools position="bottom-right" /> */} {/* <TanStackRouterDevtools position="bottom-right" /> */}
<CortexFailureDialog /> <CortexFailureDialog />
<ToolApproval /> <ToolApproval />
<OutOfContextPromiseModal />
</Fragment> </Fragment>
) )
} }

View File

@ -18,7 +18,6 @@ import { useAppState } from '@/hooks/useAppState'
import DropdownAssistant from '@/containers/DropdownAssistant' import DropdownAssistant from '@/containers/DropdownAssistant'
import { useAssistant } from '@/hooks/useAssistant' import { useAssistant } from '@/hooks/useAssistant'
import { useAppearance } from '@/hooks/useAppearance' import { useAppearance } from '@/hooks/useAppearance'
import { useOutOfContextPromiseModal } from '@/containers/dialogs/OutOfContextDialog'
// as route.threadsDetail // as route.threadsDetail
export const Route = createFileRoute('/threads/$threadId')({ export const Route = createFileRoute('/threads/$threadId')({
@ -48,8 +47,6 @@ function ThreadDetail() {
const scrollContainerRef = useRef<HTMLDivElement>(null) const scrollContainerRef = useRef<HTMLDivElement>(null)
const isFirstRender = useRef(true) const isFirstRender = useRef(true)
const messagesCount = useMemo(() => messages?.length ?? 0, [messages]) const messagesCount = useMemo(() => messages?.length ?? 0, [messages])
const { showModal, PromiseModal: OutOfContextModal } =
useOutOfContextPromiseModal()
// Function to check scroll position and scrollbar presence // Function to check scroll position and scrollbar presence
const checkScrollState = () => { const checkScrollState = () => {
@ -196,8 +193,6 @@ function ThreadDetail() {
if (!messages || !threadModel) return null if (!messages || !threadModel) return null
const contextOverflowModalComponent = <OutOfContextModal />
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<HeaderPage> <HeaderPage>
@ -243,8 +238,6 @@ function ThreadDetail() {
)) ))
} }
index={index} index={index}
showContextOverflowModal={showModal}
contextOverflowModal={contextOverflowModalComponent}
/> />
</div> </div>
) )