Skip to content

Commit 0af271b

Browse files
authored
Merge pull request #5542 from menloresearch/fix/increase-context-window-could-not-popup
2 parents 906c539 + 16aab0d commit 0af271b

File tree

7 files changed

+131
-131
lines changed

7 files changed

+131
-131
lines changed

web-app/src/containers/ChatInput.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import { ModelLoader } from '@/containers/loaders/ModelLoader'
3535
import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable'
3636
import { getConnectedServers } from '@/services/mcp'
3737
import { stopAllModels } from '@/services/models'
38-
import { useOutOfContextPromiseModal } from './dialogs/OutOfContextDialog'
3938

4039
type ChatInputProps = {
4140
className?: string
@@ -55,8 +54,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
5554
const { t } = useTranslation()
5655
const { spellCheckChatInput } = useGeneralSetting()
5756

58-
const { showModal, PromiseModal: OutOfContextModal } =
59-
useOutOfContextPromiseModal()
6057
const maxRows = 10
6158

6259
const { selectedModel } = useModelProvider()
@@ -107,7 +104,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
107104
return
108105
}
109106
setMessage('')
110-
sendMessage(prompt, showModal)
107+
sendMessage(prompt)
111108
}
112109

113110
useEffect(() => {
@@ -599,7 +596,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
599596
</div>
600597
</div>
601598
)}
602-
<OutOfContextModal />
603599
</div>
604600
)
605601
}

web-app/src/containers/ThreadContent.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ export const ThreadContent = memo(
8383
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8484
streamTools?: any
8585
contextOverflowModal?: React.ReactNode | null
86-
showContextOverflowModal?: () => Promise<unknown>
8786
}
8887
) => {
8988
const [message, setMessage] = useState(item.content?.[0]?.text?.value || '')
@@ -134,10 +133,7 @@ export const ThreadContent = memo(
134133
}
135134
if (toSendMessage) {
136135
deleteMessage(toSendMessage.thread_id, toSendMessage.id ?? '')
137-
sendMessage(
138-
toSendMessage.content?.[0]?.text?.value || '',
139-
item.showContextOverflowModal
140-
)
136+
sendMessage(toSendMessage.content?.[0]?.text?.value || '')
141137
}
142138
}, [deleteMessage, getMessages, item, sendMessage])
143139

@@ -179,16 +175,9 @@ export const ThreadContent = memo(
179175
deleteMessage(threadMessages[i].thread_id, threadMessages[i].id)
180176
}
181177

182-
sendMessage(message, item.showContextOverflowModal)
178+
sendMessage(message)
183179
},
184-
[
185-
deleteMessage,
186-
getMessages,
187-
item.thread_id,
188-
message,
189-
sendMessage,
190-
item.showContextOverflowModal,
191-
]
180+
[deleteMessage, getMessages, item.thread_id, message, sendMessage]
192181
)
193182

194183
const isToolCalls =

web-app/src/containers/dialogs/OutOfContextDialog.tsx

Lines changed: 65 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -8,108 +8,76 @@ import {
88
DialogTitle,
99
} from '@/components/ui/dialog'
1010

11-
import { ReactNode, useCallback, useState } from 'react'
1211
import { Button } from '@/components/ui/button'
12+
import { useContextSizeApproval } from '@/hooks/useModelContextApproval'
1313

14-
export function useOutOfContextPromiseModal() {
15-
const [isOpen, setIsOpen] = useState(false)
16-
const [modalProps, setModalProps] = useState<{
17-
resolveRef:
18-
| ((value: 'ctx_len' | 'context_shift' | undefined) => void)
19-
| null
20-
}>({
21-
resolveRef: null,
22-
})
23-
// Function to open the modal and return a Promise
24-
const showModal = useCallback(() => {
25-
return new Promise((resolve) => {
26-
setModalProps({
27-
resolveRef: resolve,
28-
})
29-
setIsOpen(true)
30-
})
31-
}, [])
14+
export default function OutOfContextPromiseModal() {
15+
const { isModalOpen, modalProps, setModalOpen } = useContextSizeApproval()
16+
if (!modalProps) {
17+
return null
18+
}
19+
const { onApprove, onDeny } = modalProps
3220

33-
const PromiseModal = useCallback((): ReactNode => {
34-
if (!isOpen) {
35-
return null
36-
}
21+
const handleContextLength = () => {
22+
onApprove('ctx_len')
23+
}
3724

38-
const handleContextLength = () => {
39-
setIsOpen(false)
40-
if (modalProps.resolveRef) {
41-
modalProps.resolveRef('ctx_len')
42-
}
43-
}
25+
const handleContextShift = () => {
26+
onApprove('context_shift')
27+
}
4428

45-
const handleContextShift = () => {
46-
setIsOpen(false)
47-
if (modalProps.resolveRef) {
48-
modalProps.resolveRef('context_shift')
49-
}
50-
}
51-
const handleCancel = () => {
52-
setIsOpen(false)
53-
if (modalProps.resolveRef) {
54-
modalProps.resolveRef(undefined)
55-
}
29+
const handleDialogOpen = (open: boolean) => {
30+
setModalOpen(open)
31+
if (!open) {
32+
onDeny()
5633
}
34+
}
5735

58-
return (
59-
<Dialog
60-
open={isOpen}
61-
onOpenChange={(open) => {
62-
setIsOpen(open)
63-
if (!open) handleCancel()
64-
}}
65-
>
66-
<DialogContent>
67-
<DialogHeader>
68-
<DialogTitle>
69-
{t('outOfContextError.title', 'Out of context error')}
70-
</DialogTitle>
71-
</DialogHeader>
72-
<DialogDescription>
73-
{t(
74-
'outOfContextError.description',
75-
'This chat is reaching the AI’s memory limit, like a whiteboard filling up. We can expand the memory window (called context size) so it remembers more, but it may use more of your computer’s memory. We can also truncate the input, which means it will forget some of the chat history to make room for new messages.'
76-
)}
77-
<br />
78-
<br />
79-
{t(
80-
'outOfContextError.increaseContextSizeDescription',
81-
'Do you want to increase the context size?'
82-
)}
83-
</DialogDescription>
84-
<DialogFooter className="flex gap-2">
85-
<Button
86-
variant="default"
87-
className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4"
88-
onClick={() => {
89-
handleContextShift()
90-
setIsOpen(false)
91-
}}
92-
>
93-
{t('outOfContextError.truncateInput', 'Truncate Input')}
94-
</Button>
95-
<Button
96-
asChild
97-
onClick={() => {
98-
handleContextLength()
99-
setIsOpen(false)
100-
}}
101-
>
102-
<span className="text-main-view-fg/70">
103-
{t(
104-
'outOfContextError.increaseContextSize',
105-
'Increase Context Size'
106-
)}
107-
</span>
108-
</Button>
109-
</DialogFooter>
110-
</DialogContent>
111-
</Dialog>
112-
)
113-
}, [isOpen, modalProps])
114-
return { showModal, PromiseModal }
36+
return (
37+
<Dialog open={isModalOpen} onOpenChange={handleDialogOpen}>
38+
<DialogContent>
39+
<DialogHeader>
40+
<DialogTitle>
41+
{t('outOfContextError.title', 'Out of context error')}
42+
</DialogTitle>
43+
</DialogHeader>
44+
<DialogDescription>
45+
{t(
46+
'outOfContextError.description',
47+
'This chat is reaching the AI’s memory limit, like a whiteboard filling up. We can expand the memory window (called context size) so it remembers more, but it may use more of your computer’s memory. We can also truncate the input, which means it will forget some of the chat history to make room for new messages.'
48+
)}
49+
<br />
50+
<br />
51+
{t(
52+
'outOfContextError.increaseContextSizeDescription',
53+
'Do you want to increase the context size?'
54+
)}
55+
</DialogDescription>
56+
<DialogFooter className="flex gap-2">
57+
<Button
58+
variant="default"
59+
className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4"
60+
onClick={() => {
61+
handleContextShift()
62+
}}
63+
>
64+
{t('outOfContextError.truncateInput', 'Truncate Input')}
65+
</Button>
66+
<Button
67+
asChild
68+
onClick={() => {
69+
handleContextLength()
70+
}}
71+
>
72+
<span className="text-main-view-fg/70">
73+
{t(
74+
'outOfContextError.increaseContextSize',
75+
'Increase Context Size'
76+
)}
77+
</span>
78+
</Button>
79+
</DialogFooter>
80+
</DialogContent>
81+
</Dialog>
82+
)
11583
}

web-app/src/hooks/useChat.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { useToolApproval } from '@/hooks/useToolApproval'
3030
import { useToolAvailable } from '@/hooks/useToolAvailable'
3131
import { OUT_OF_CONTEXT_SIZE } from '@/utils/error'
3232
import { updateSettings } from '@/services/providers'
33+
import { useContextSizeApproval } from './useModelContextApproval'
3334

3435
export const useChat = () => {
3536
const { prompt, setPrompt } = usePrompt()
@@ -47,6 +48,8 @@ export const useChat = () => {
4748

4849
const { approvedTools, showApprovalModal, allowAllMCPPermissions } =
4950
useToolApproval()
51+
const { showApprovalModal: showIncreaseContextSizeModal } =
52+
useContextSizeApproval()
5053
const { getDisabledToolsForThread } = useToolAvailable()
5154

5255
const { getProviderByName, selectedModel, selectedProvider } =
@@ -223,11 +226,7 @@ export const useChat = () => {
223226
)
224227

225228
const sendMessage = useCallback(
226-
async (
227-
message: string,
228-
showModal?: () => Promise<unknown>,
229-
troubleshooting = true
230-
) => {
229+
async (message: string, troubleshooting = true) => {
231230
const activeThread = await getCurrentThread()
232231

233232
resetTokenSpeed()
@@ -361,7 +360,7 @@ export const useChat = () => {
361360
selectedModel &&
362361
troubleshooting
363362
) {
364-
const method = await showModal?.()
363+
const method = await showIncreaseContextSizeModal()
365364
if (method === 'ctx_len') {
366365
/// Increase context size
367366
activeProvider = await increaseModelContextSize(
@@ -447,15 +446,15 @@ export const useChat = () => {
447446
updateThreadTimestamp,
448447
setPrompt,
449448
selectedModel,
450-
currentAssistant?.instructions,
451-
currentAssistant.parameters,
449+
currentAssistant,
452450
tools,
453451
updateLoadingModel,
454452
getDisabledToolsForThread,
455453
approvedTools,
456454
allowAllMCPPermissions,
457455
showApprovalModal,
458456
updateTokenSpeed,
457+
showIncreaseContextSizeModal,
459458
increaseModelContextSize,
460459
toggleOnContextShifting,
461460
]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { create } from 'zustand'
2+
3+
export type ApprovalModalProps = {
4+
onApprove: (method: 'ctx_len' | 'context_shift') => void
5+
onDeny: () => void
6+
}
7+
8+
type ApprovalState = {
9+
// Modal state
10+
isModalOpen: boolean
11+
modalProps: ApprovalModalProps | null
12+
13+
showApprovalModal: () => Promise<'ctx_len' | 'context_shift' | undefined>
14+
closeModal: () => void
15+
setModalOpen: (open: boolean) => void
16+
}
17+
18+
export const useContextSizeApproval = create<ApprovalState>()((set, get) => ({
19+
isModalOpen: false,
20+
modalProps: null,
21+
22+
showApprovalModal: async () => {
23+
return new Promise<'ctx_len' | 'context_shift' | undefined>((resolve) => {
24+
set({
25+
isModalOpen: true,
26+
modalProps: {
27+
onApprove: (method) => {
28+
get().closeModal()
29+
resolve(method)
30+
},
31+
onDeny: () => {
32+
get().closeModal()
33+
resolve(undefined)
34+
},
35+
},
36+
})
37+
})
38+
},
39+
40+
closeModal: () => {
41+
set({
42+
isModalOpen: false,
43+
modalProps: null,
44+
})
45+
},
46+
47+
setModalOpen: (open: boolean) => {
48+
set({ isModalOpen: open })
49+
if (!open) {
50+
get().closeModal()
51+
}
52+
},
53+
}))

web-app/src/routes/__root.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { AnalyticProvider } from '@/providers/AnalyticProvider'
1818
import { useLeftPanel } from '@/hooks/useLeftPanel'
1919
import { cn } from '@/lib/utils'
2020
import ToolApproval from '@/containers/dialogs/ToolApproval'
21+
import OutOfContextPromiseModal from '@/containers/dialogs/OutOfContextDialog'
2122

2223
export const Route = createRootRoute({
2324
component: RootLayout,
@@ -94,6 +95,7 @@ function RootLayout() {
9495
{/* <TanStackRouterDevtools position="bottom-right" /> */}
9596
<CortexFailureDialog />
9697
<ToolApproval />
98+
<OutOfContextPromiseModal />
9799
</Fragment>
98100
)
99101
}

0 commit comments

Comments
 (0)