diff --git a/.github/workflows/template-tauri-build-macos-external.yml b/.github/workflows/template-tauri-build-macos-external.yml index 77d8f1e71..cce4ba078 100644 --- a/.github/workflows/template-tauri-build-macos-external.yml +++ b/.github/workflows/template-tauri-build-macos-external.yml @@ -96,7 +96,8 @@ jobs: - name: Build app run: | make build - env: + env: + NODE_OPTIONS: "--max-old-space-size=4196" APP_PATH: '.' - name: Upload Artifact diff --git a/.github/workflows/template-tauri-build-macos.yml b/.github/workflows/template-tauri-build-macos.yml index c1fdcaf19..bb7515f82 100644 --- a/.github/workflows/template-tauri-build-macos.yml +++ b/.github/workflows/template-tauri-build-macos.yml @@ -173,6 +173,7 @@ jobs: run: | make build env: + NODE_OPTIONS: "--max-old-space-size=4196" GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} APP_PATH: '.' POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} diff --git a/web-app/package.json b/web-app/package.json index bd87f937a..4117e35e1 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -39,6 +39,10 @@ "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-switch": "1.2.2", "@radix-ui/react-tooltip": "1.2.4", + "@streamdown/cjk": "^1.0.1", + "@streamdown/code": "^1.0.1", + "@streamdown/math": "^1.0.1", + "@streamdown/mermaid": "^1.0.1", "@tabler/icons-react": "3.34.0", "@tailwindcss/vite": "4.1.4", "@tanstack/react-router": "^1.121.34", @@ -86,7 +90,7 @@ "remark-math": "6.0.0", "shiki": "^3.19.0", "sonner": "2.0.5", - "streamdown": "npm:@janhq/streamdown@^2.0.2", + "streamdown": "npm:@janhq/streamdown@^2.1.1", "tailwindcss": "4.1.17", "token.js": "npm:token.js-fork@0.7.31", "tw-animate-css": "1.2.8", diff --git a/web-app/src/containers/ChatInput.tsx b/web-app/src/containers/ChatInput.tsx index e776ffc07..04c1aff31 100644 --- a/web-app/src/containers/ChatInput.tsx +++ b/web-app/src/containers/ChatInput.tsx @@ -154,12 +154,6 @@ const ChatInput = ({ const [isDragOver, setIsDragOver] = useState(false) const [hasMmproj, setHasMmproj] = useState(false) const activeModels = useAppState(useShallow((state) => state.activeModels)) - const hasActiveModels = useMemo( - () => - activeModels.length > 0 && - activeModels.some((e) => e === selectedModel?.id), - [activeModels, selectedModel?.id] - ) // Jan Browser Extension hook const { @@ -1694,7 +1688,6 @@ const ChatInput = ({
{selectedProvider === 'llamacpp' && - hasActiveModels && tokenCounterCompact && !initialMessage && (threadMessages?.length > 0 || prompt.trim().length > 0) && ( @@ -1762,7 +1755,6 @@ const ChatInput = ({ )} {selectedProvider === 'llamacpp' && - hasActiveModels && !tokenCounterCompact && !initialMessage && (threadMessages?.length > 0 || prompt.trim().length > 0) && ( diff --git a/web-app/src/containers/MessageItem.tsx b/web-app/src/containers/MessageItem.tsx index 274348010..69a49ba42 100644 --- a/web-app/src/containers/MessageItem.tsx +++ b/web-app/src/containers/MessageItem.tsx @@ -357,7 +357,7 @@ export const MessageItem = memo( {/* Message actions for assistant messages (non-tool) */} {message.role === 'assistant' && - message.parts.some((p) => p.type === 'text') && ( + message.parts.some((p) => p.type === 'text' && p.text.length > 0) && (
{ expect(result.current.deletedServerKeys).toContain('lifecycle-server') }) }) - - describe('Proactive Mode Settings', () => { - it('should have proactiveMode in default settings', () => { - expect(DEFAULT_MCP_SETTINGS.proactiveMode).toBeDefined() - expect(DEFAULT_MCP_SETTINGS.proactiveMode).toBe(false) - }) - - it('should initialize proactiveMode as false', () => { - const { result } = renderHook(() => useMCPServers()) - - expect(result.current.settings.proactiveMode).toBe(false) - }) - - it('should update proactiveMode using updateSettings', () => { - const { result } = renderHook(() => useMCPServers()) - - act(() => { - result.current.updateSettings({ proactiveMode: true }) - }) - - expect(result.current.settings.proactiveMode).toBe(true) - }) - - it('should toggle proactiveMode on and off', () => { - const { result } = renderHook(() => useMCPServers()) - - // Initially false - expect(result.current.settings.proactiveMode).toBe(false) - - // Toggle to true - act(() => { - result.current.updateSettings({ proactiveMode: true }) - }) - - expect(result.current.settings.proactiveMode).toBe(true) - - // Toggle back to false - act(() => { - result.current.updateSettings({ proactiveMode: false }) - }) - - expect(result.current.settings.proactiveMode).toBe(false) - }) - - it('should not affect other settings when updating proactiveMode', () => { - const { result } = renderHook(() => useMCPServers()) - - const originalSettings = { ...result.current.settings } - - act(() => { - result.current.updateSettings({ proactiveMode: true }) - }) - - expect(result.current.settings.toolCallTimeoutSeconds).toBe( - originalSettings.toolCallTimeoutSeconds - ) - expect(result.current.settings.baseRestartDelayMs).toBe( - originalSettings.baseRestartDelayMs - ) - expect(result.current.settings.maxRestartDelayMs).toBe( - originalSettings.maxRestartDelayMs - ) - expect(result.current.settings.backoffMultiplier).toBe( - originalSettings.backoffMultiplier - ) - }) - - it('should update proactiveMode along with other settings', () => { - const { result } = renderHook(() => useMCPServers()) - - act(() => { - result.current.updateSettings({ - proactiveMode: true, - toolCallTimeoutSeconds: 60, - }) - }) - - expect(result.current.settings.proactiveMode).toBe(true) - expect(result.current.settings.toolCallTimeoutSeconds).toBe(60) - }) - - it('should call syncServers with proactiveMode included in settings', async () => { - const { result } = renderHook(() => useMCPServers()) - - act(() => { - result.current.updateSettings({ proactiveMode: true }) - }) - - await act(async () => { - await result.current.syncServers() - }) - - expect(mockUpdateMCPConfig).toHaveBeenCalledWith( - expect.stringContaining('proactiveMode') - ) - }) - - it('should persist proactiveMode setting through setSettings', () => { - const { result } = renderHook(() => useMCPServers()) - - const newSettings = { - ...DEFAULT_MCP_SETTINGS, - proactiveMode: true, - toolCallTimeoutSeconds: 45, - } - - act(() => { - result.current.setSettings(newSettings) - }) - - expect(result.current.settings.proactiveMode).toBe(true) - expect(result.current.settings.toolCallTimeoutSeconds).toBe(45) - }) - }) }) diff --git a/web-app/src/hooks/useJanBrowserExtension.ts b/web-app/src/hooks/useJanBrowserExtension.ts index 1adb6fdef..6c9e666cc 100644 --- a/web-app/src/hooks/useJanBrowserExtension.ts +++ b/web-app/src/hooks/useJanBrowserExtension.ts @@ -176,10 +176,6 @@ export function useJanBrowserExtension() { } catch (error) { // Don't show error if cancelled if (cancelledRef.current) return - - toast.error('Failed to toggle Jan Browser MCP', { - description: error instanceof Error ? error.message : String(error), - }) console.error('Error toggling Jan Browser MCP:', error) setDialogOpen(false) setDialogState('closed') diff --git a/web-app/src/hooks/useMCPServers.ts b/web-app/src/hooks/useMCPServers.ts index c0dad16e2..9c6d197f4 100644 --- a/web-app/src/hooks/useMCPServers.ts +++ b/web-app/src/hooks/useMCPServers.ts @@ -24,7 +24,6 @@ export type MCPSettings = { baseRestartDelayMs: number maxRestartDelayMs: number backoffMultiplier: number - proactiveMode: boolean } export const DEFAULT_MCP_SETTINGS: MCPSettings = { @@ -32,7 +31,6 @@ export const DEFAULT_MCP_SETTINGS: MCPSettings = { baseRestartDelayMs: 1000, maxRestartDelayMs: 30000, backoffMultiplier: 2, - proactiveMode: false, } type MCPServerStoreState = { diff --git a/web-app/src/lib/custom-chat-transport.ts b/web-app/src/lib/custom-chat-transport.ts index 5cef9149e..b85863e3b 100644 --- a/web-app/src/lib/custom-chat-transport.ts +++ b/web-app/src/lib/custom-chat-transport.ts @@ -41,9 +41,6 @@ export type ServiceHub = { Array<{ name: string; description: string; inputSchema: unknown }> > } - models(): { - startModel(provider: ProviderObject, model: string): Promise - } } export class CustomChatTransport implements ChatTransport { @@ -225,20 +222,17 @@ export class CustomChatTransport implements ChatTransport { const updatedProvider = useModelProvider .getState() .getProviderByName(this.provider.provider) - // Start the model (this will be a no-op for remote providers) - await this.serviceHub - .models() - .startModel(updatedProvider ?? this.provider, this.modelId) // Create the model using the factory + // For llamacpp provider, startModel is called internally in ModelFactory.createLlamaCppModel this.model = await ModelFactory.createModel( this.modelId, updatedProvider ?? this.provider ) } catch (error) { - console.error('Failed to start model:', error) + console.error('Failed to create model:', error) throw new Error( - `Failed to start model: ${error instanceof Error ? error.message : String(error)}` + `Failed to create model: ${error instanceof Error ? error.message : JSON.stringify(error)}` ) } } else { diff --git a/web-app/src/lib/model-factory.ts b/web-app/src/lib/model-factory.ts index 5036dea04..87cf89140 100644 --- a/web-app/src/lib/model-factory.ts +++ b/web-app/src/lib/model-factory.ts @@ -106,7 +106,7 @@ export class ModelFactory { switch (providerName) { case 'llamacpp': - return this.createLlamaCppModel(modelId) + return this.createLlamaCppModel(modelId, provider) case 'anthropic': return this.createAnthropicModel(modelId, provider) @@ -131,11 +131,29 @@ export class ModelFactory { } /** - * Create a llamacpp model by finding the running session + * Create a llamacpp model by starting the model and finding the running session */ private static async createLlamaCppModel( - modelId: string + modelId: string, + provider?: ProviderObject ): Promise { + // Start the model first if provider is available + if (provider) { + try { + const { useServiceStore } = await import('@/hooks/useServiceHub') + const serviceHub = useServiceStore.getState().serviceHub + + if (serviceHub) { + await serviceHub.models().startModel(provider, modelId) + } + } catch (error) { + console.error('Failed to start llamacpp model:', error) + throw new Error( + `Failed to start model: ${error instanceof Error ? error.message : JSON.stringify(error)}` + ) + } + } + // Get session info which includes port and api_key const sessionInfo = await invoke( 'plugin:llamacpp|find_session_by_model', diff --git a/web-app/src/locales/cs/mcp-servers.json b/web-app/src/locales/cs/mcp-servers.json index 951266dda..515e9ce47 100644 --- a/web-app/src/locales/cs/mcp-servers.json +++ b/web-app/src/locales/cs/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Nakonfigurujte, jak Jan spravuje a opakuje pokusy se servery MCP.", "toolCallTimeout": "Časový limit volání nástroje (sekundy)", "toolCallTimeoutDesc": "Maximální doba čekání na odpověď nástroje MCP před vypršením časového limitu." - }, - "proactiveMode": "Proaktivní režim používání prohlížeče", - "proactiveModeDesc": "Pokud je povoleno, automaticky zachytává snímky obrazovky prohlížeče, aby poskytl další kontext pro úlohy automatizace prohlížeče. Vyžaduje Jan Browser MCP s modelem pro vidění a použití nástrojů." + } } diff --git a/web-app/src/locales/de-DE/mcp-servers.json b/web-app/src/locales/de-DE/mcp-servers.json index 7acbc99c6..186ee9ca3 100644 --- a/web-app/src/locales/de-DE/mcp-servers.json +++ b/web-app/src/locales/de-DE/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Konfiguriere, wie Jan MCP-Server verwaltet und erneut versucht.", "toolCallTimeout": "Zeitlimit für Tool-Aufruf (Sekunden)", "toolCallTimeoutDesc": "Maximale Wartezeit auf eine Antwort eines MCP-Tools, bevor abgebrochen wird." - }, - "proactiveMode": "Browser Use Proaktiv-Modus", - "proactiveModeDesc": "Wenn aktiviert, werden automatisch Browser-Screenshots erfasst, um zusätzlichen Kontext für Browser-Automatisierungsaufgaben bereitzustellen. Erfordert Jan Browser MCP mit Vision- und Tool-Nutzungsmodell." + } } diff --git a/web-app/src/locales/en/mcp-servers.json b/web-app/src/locales/en/mcp-servers.json index 7825bd651..2c3c43c43 100644 --- a/web-app/src/locales/en/mcp-servers.json +++ b/web-app/src/locales/en/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Configure how Jan manages and retries MCP servers.", "toolCallTimeout": "Tool call timeout (seconds)", "toolCallTimeoutDesc": "Maximum time to wait for an MCP tool response before timing out." - }, - "proactiveMode": "Browser Use Proactive Mode", - "proactiveModeDesc": "When enabled, automatically captures browser screenshots to provide additional context for browser automation tasks. Requires Jan Browser MCP with vision and tool use model." + } } diff --git a/web-app/src/locales/fr/mcp-servers.json b/web-app/src/locales/fr/mcp-servers.json index 3ca4cc710..98fd868e6 100644 --- a/web-app/src/locales/fr/mcp-servers.json +++ b/web-app/src/locales/fr/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Configurez comment Jan gère et réessaye les serveurs MCP.", "toolCallTimeout": "Délai d'appel d'outil (secondes)", "toolCallTimeoutDesc": "Temps maximum d'attente pour une réponse d'outil MCP avant l'expiration du délai." - }, - "proactiveMode": "Mode Proactif d'Utilisation du Navigateur", - "proactiveModeDesc": "Lorsqu'activé, capture automatiquement des captures d'écran du navigateur pour fournir un contexte supplémentaire pour les tâches d'automatisation du navigateur. Nécessite Jan Browser MCP avec un modèle de vision et d'utilisation d'outils." + } } diff --git a/web-app/src/locales/id/mcp-servers.json b/web-app/src/locales/id/mcp-servers.json index d0194b249..f6ac5e322 100644 --- a/web-app/src/locales/id/mcp-servers.json +++ b/web-app/src/locales/id/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Atur bagaimana Jan mengelola dan mencoba ulang server MCP.", "toolCallTimeout": "Batas waktu pemanggilan alat (detik)", "toolCallTimeoutDesc": "Waktu maksimum menunggu respons alat MCP sebelum waktu habis." - }, - "proactiveMode": "Mode Proaktif Penggunaan Browser", - "proactiveModeDesc": "Jika diaktifkan, secara otomatis menangkap tangkapan layar browser untuk memberikan konteks tambahan untuk tugas otomasi browser. Memerlukan Jan Browser MCP dengan model vision dan penggunaan tool." + } } diff --git a/web-app/src/locales/ja/mcp-servers.json b/web-app/src/locales/ja/mcp-servers.json index b59689168..8fdcb38aa 100644 --- a/web-app/src/locales/ja/mcp-servers.json +++ b/web-app/src/locales/ja/mcp-servers.json @@ -59,7 +59,5 @@ "description": "JanがMCPサーバーを管理し再試行する方法を設定します。", "toolCallTimeout": "ツール呼び出しタイムアウト(秒)", "toolCallTimeoutDesc": "MCPツールの応答を待機する最大時間(タイムアウトまで)。" - }, - "proactiveMode": "ブラウザ使用プロアクティブモード", - "proactiveModeDesc": "有効にすると、ブラウザの自動化タスクに追加のコンテキストを提供するために、ブラウザのスクリーンショットを自動的にキャプチャします。VisionとToolを使用するモデルを備えたJan Browser MCPが必要です。" + } } diff --git a/web-app/src/locales/pl/mcp-servers.json b/web-app/src/locales/pl/mcp-servers.json index ce11a0e4c..b1b6cd177 100644 --- a/web-app/src/locales/pl/mcp-servers.json +++ b/web-app/src/locales/pl/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Skonfiguruj, jak Jan zarządza i ponawia próby połączenia z serwerami MCP.", "toolCallTimeout": "Limit czasu wywołania narzędzia (sekundy)", "toolCallTimeoutDesc": "Maksymalny czas oczekiwania na odpowiedź narzędzia MCP przed przekroczeniem limitu czasu." - }, - "proactiveMode": "Tryb Proaktywnego Użycia Przeglądarki", - "proactiveModeDesc": "Po włączeniu automatycznie przechwytuje zrzuty ekranu przeglądarki, aby zapewnić dodatkowy kontekst dla zadań automatyzacji przeglądarki. Wymaga Jan Browser MCP z modelem vision i narzędzi." + } } diff --git a/web-app/src/locales/pt-BR/mcp-servers.json b/web-app/src/locales/pt-BR/mcp-servers.json index 2b0413e34..ce8985c27 100644 --- a/web-app/src/locales/pt-BR/mcp-servers.json +++ b/web-app/src/locales/pt-BR/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Configure como o Jan gerencia e tenta novamente os servidores MCP.", "toolCallTimeout": "Tempo limite de chamada da ferramenta (segundos)", "toolCallTimeoutDesc": "Tempo máximo de espera por uma resposta da ferramenta MCP antes de atingir o tempo limite." - }, - "proactiveMode": "Modo Proativo de Uso do Navegador", - "proactiveModeDesc": "Quando habilitado, captura automaticamente capturas de tela do navegador para fornecer contexto adicional para tarefas de automação do navegador. Requer Jan Browser MCP com modelo de visão e uso de ferramentas." + } } diff --git a/web-app/src/locales/ru/mcp-servers.json b/web-app/src/locales/ru/mcp-servers.json index b6644939b..ce7645623 100644 --- a/web-app/src/locales/ru/mcp-servers.json +++ b/web-app/src/locales/ru/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Настройте, как Jan управляет и перезапускает серверы MCP.", "toolCallTimeout": "Время ожидания вызова инструмента (секунды)", "toolCallTimeoutDesc": "Максимальное время ожидания ответа от инструмента MCP." - }, - "proactiveMode": "Режим проактивного использования браузера", - "proactiveModeDesc": "При включении автоматически создаёт снимки экрана браузера для предоставления дополнительного контекста задачам автоматизации браузера. Требуется браузер Jan MCP и модель с поддержкой зрения и использования инструментов." + } } diff --git a/web-app/src/locales/vn/mcp-servers.json b/web-app/src/locales/vn/mcp-servers.json index 838aec683..a6a947e76 100644 --- a/web-app/src/locales/vn/mcp-servers.json +++ b/web-app/src/locales/vn/mcp-servers.json @@ -59,7 +59,5 @@ "description": "Cấu hình cách Jan quản lý và thử lại các máy chủ MCP.", "toolCallTimeout": "Thời gian chờ lệnh (giây)", "toolCallTimeoutDesc": "Thời gian tối đa chờ phản hồi từ công cụ MCP trước khi hết thời gian." - }, - "proactiveMode": "Chế độ Chủ động Sử dụng Trình duyệt", - "proactiveModeDesc": "Khi được bật, tự động chụp ảnh màn hình trình duyệt để cung cấp ngữ cảnh bổ sung cho các tác vụ tự động hóa trình duyệt. Yêu cầu Jan Browser MCP với mô hình vision và sử dụng công cụ." + } } diff --git a/web-app/src/locales/zh-CN/mcp-servers.json b/web-app/src/locales/zh-CN/mcp-servers.json index 8cfcc1b32..9b7ada378 100644 --- a/web-app/src/locales/zh-CN/mcp-servers.json +++ b/web-app/src/locales/zh-CN/mcp-servers.json @@ -59,7 +59,5 @@ "description": "配置 Jan 如何管理和重试 MCP 服务器。", "toolCallTimeout": "工具调用超时时间(秒)", "toolCallTimeoutDesc": "在超时前等待 MCP 工具响应的最长时间。" - }, - "proactiveMode": "浏览器使用主动模式", - "proactiveModeDesc": "启用后,会自动捕获浏览器截图,为浏览器自动化任务提供额外的上下文信息。需要具备视觉和工具使用模型的 Jan Browser MCP。" + } } diff --git a/web-app/src/locales/zh-TW/mcp-servers.json b/web-app/src/locales/zh-TW/mcp-servers.json index c40f6221e..5c7eed32d 100644 --- a/web-app/src/locales/zh-TW/mcp-servers.json +++ b/web-app/src/locales/zh-TW/mcp-servers.json @@ -59,7 +59,5 @@ "description": "設定 Jan 如何管理及重試 MCP 伺服器。", "toolCallTimeout": "工具呼叫逾時(秒)", "toolCallTimeoutDesc": "等待 MCP 工具回應的最長時間,超過即逾時。" - }, - "proactiveMode": "瀏覽器使用主動模式", - "proactiveModeDesc": "啟用後,會自動擷取瀏覽器螢幕截圖,為瀏覽器自動化工作提供額外的情境資訊。需要具備視覺與工具使用模型的 Jan Browser MCP。" + } } diff --git a/web-app/src/routes/settings/mcp-servers.tsx b/web-app/src/routes/settings/mcp-servers.tsx index 70f615b0f..ee17f4551 100644 --- a/web-app/src/routes/settings/mcp-servers.tsx +++ b/web-app/src/routes/settings/mcp-servers.tsx @@ -456,28 +456,6 @@ function MCPServersDesktop() { /> } /> - - {t('mcp-servers:proactiveMode')} -
- {t('mcp-servers:experimental')} -
-
- } - description={t('mcp-servers:proactiveModeDesc')} - actions={ -
- { - updateSettings({ proactiveMode: checked }) - void syncServers() - }} - /> -
- } - /> {Object.keys(mcpServers).length === 0 ? ( diff --git a/web-app/src/routes/threads/$threadId.tsx b/web-app/src/routes/threads/$threadId.tsx index fc74fc023..b7aaccee7 100644 --- a/web-app/src/routes/threads/$threadId.tsx +++ b/web-app/src/routes/threads/$threadId.tsx @@ -45,6 +45,9 @@ import { processAttachmentsForSend } from '@/lib/attachmentProcessing' import { useAttachments } from '@/hooks/useAttachments' import { PromptProgress } from '@/components/PromptProgress' import { useToolAvailable } from '@/hooks/useToolAvailable' +import { OUT_OF_CONTEXT_SIZE } from '@/utils/error' +import { Button } from '@/components/ui/button' +import { IconAlertCircle } from '@tabler/icons-react' const CHAT_STATUS = { STREAMING: 'streaming', @@ -151,6 +154,7 @@ function ThreadDetail() { const { messages: chatMessages, status, + error, sendMessage, regenerate, setMessages: setChatMessages, @@ -533,12 +537,7 @@ function ThreadDetail() { } })() } - }, [ - threadId, - languageModelId, - languageModelProvider, - processAndSendMessage, - ]) + }, [threadId, languageModelId, languageModelProvider, processAndSendMessage]) // Handle submit from ChatInput const handleSubmit = useCallback( @@ -600,6 +599,60 @@ function ThreadDetail() { // and generating a new response from the selected message regenerate(messageId ? { messageId } : undefined) } + + // Handler for increasing context size + const handleContextSizeIncrease = useCallback(async () => { + if (!selectedModel) return + + const updateProvider = useModelProvider.getState().updateProvider + const provider = getProviderByName(selectedProvider) + if (!provider) return + + const modelIndex = provider.models.findIndex( + (m) => m.id === selectedModel.id + ) + if (modelIndex === -1) return + + const model = provider.models[modelIndex] + + // Increase context length by 50% + const currentCtxLen = + (model.settings?.ctx_len?.controller_props?.value as number) ?? 8192 + const newCtxLen = Math.round(Math.max(8192, currentCtxLen) * 1.5) + + const updatedModel = { + ...model, + settings: { + ...model.settings, + ctx_len: { + ...(model.settings?.ctx_len ?? {}), + controller_props: { + ...(model.settings?.ctx_len?.controller_props ?? {}), + value: newCtxLen, + }, + }, + }, + } + + const updatedModels = [...provider.models] + updatedModels[modelIndex] = updatedModel as Model + + updateProvider(provider.provider, { + models: updatedModels, + }) + + await serviceHub.models().stopModel(selectedModel.id) + + setTimeout(() => { + handleRegenerate() + }, 1000) + }, [ + selectedModel, + selectedProvider, + getProviderByName, + serviceHub, + ]) + const threadModel = useMemo(() => thread?.model, [thread]) if (!threadModel) return null @@ -657,6 +710,36 @@ function ThreadDetail() { ) })} {status === CHAT_STATUS.SUBMITTED && } + {error && ( +
+
+ +
+

+ Error generating response +

+

+ {error.message} +

+ {(error.message.toLowerCase().includes('context') && + (error.message.toLowerCase().includes('size') || + error.message.toLowerCase().includes('length') || + error.message.toLowerCase().includes('limit'))) || + error.message === OUT_OF_CONTEXT_SIZE ? ( + + ) : null} +
+
+
+ )}