From 5029c8570e446ef69813577f1bb43412d8fef71f Mon Sep 17 00:00:00 2001 From: red person Date: Tue, 2 Jun 2026 15:00:50 +0300 Subject: [PATCH] Chat: prefer active model for new desktop chats --- static/app.js | 73 ++++++++++++------------- tests/test_new_chat_model_preference.py | 44 +++++++++++++++ 2 files changed, 79 insertions(+), 38 deletions(-) create mode 100644 tests/test_new_chat_model_preference.py diff --git a/static/app.js b/static/app.js index 887bb9d..2764b90 100644 --- a/static/app.js +++ b/static/app.js @@ -85,6 +85,39 @@ async function _refreshDefaultChat() { // synchronously; later reads should call _refreshDefaultChat() first. _refreshDefaultChat(); +async function _createDirectChatFromPreferredModel() { + if (!sessionModule) return false; + + const pending = sessionModule.getPendingChat && sessionModule.getPendingChat(); + if (pending && pending.url && pending.modelId) { + sessionModule.createDirectChat(pending.url, pending.modelId, pending.endpointId); + return true; + } + + const sessions = sessionModule.getSessions(); + const currentId = sessionModule.getCurrentSessionId(); + const current = sessions.find(s => s.id === currentId); + if (current && current.endpoint_url && current.model) { + sessionModule.createDirectChat(current.endpoint_url, current.model, current.endpoint_id); + return true; + } + + const dc = await _refreshDefaultChat(); + if (dc) { + sessionModule.createDirectChat(dc.endpoint_url, dc.model, dc.endpoint_id); + return true; + } + + const withModel = sessions.filter(s => s.endpoint_url && s.model); + if (withModel.length > 0) { + const last = withModel[0]; // sessions are sorted by recent + sessionModule.createDirectChat(last.endpoint_url, last.model, last.endpoint_id); + return true; + } + + return false; +} + // ============================================ // EVENT LISTENERS INITIALIZATION // ============================================ @@ -3015,27 +3048,7 @@ function initializeEventListeners() { // Clear research mode if active const _resChk = el('research-toggle'); if (_resChk && _resChk.checked) _syncResearchIndicator(false); - // Use default chat if configured — always re-fetch so setting changes apply immediately - const dc = await _refreshDefaultChat(); - if (dc) { - sessionModule.createDirectChat(dc.endpoint_url, dc.model, dc.endpoint_id); - return; - } - const sessions = sessionModule.getSessions(); - const currentId = sessionModule.getCurrentSessionId(); - const current = sessions.find(s => s.id === currentId); - // Try current session's model first - if (current && current.endpoint_url && current.model) { - sessionModule.createDirectChat(current.endpoint_url, current.model, current.endpoint_id); - return; - } - // Fallback: find any recent session with a model - const withModel = sessions.filter(s => s.endpoint_url && s.model); - if (withModel.length > 0) { - const last = withModel[0]; // sessions are sorted by recent - sessionModule.createDirectChat(last.endpoint_url, last.model, last.endpoint_id); - return; - } + if (await _createDirectChatFromPreferredModel()) return; // No models at all — show welcome screen sessionModule.setCurrentSessionId(null); if (documentModule && documentModule.isPanelOpen && documentModule.isPanelOpen()) documentModule.closePanel(); @@ -3080,23 +3093,7 @@ function initializeEventListeners() { if (presetsModule && presetsModule.deactivateCharacter) presetsModule.deactivateCharacter(); // Clear research toggle when starting a fresh chat (not via research button) _syncResearchIndicator(false); - const dc = await _refreshDefaultChat(); - if (dc) { - sessionModule.createDirectChat(dc.endpoint_url, dc.model, dc.endpoint_id); - return; - } - const sessions = sessionModule.getSessions(); - const currentId = sessionModule.getCurrentSessionId(); - const current = sessions.find(s => s.id === currentId); - if (current && current.endpoint_url && current.model) { - sessionModule.createDirectChat(current.endpoint_url, current.model, current.endpoint_id); - return; - } - const withModel = sessions.filter(s => s.endpoint_url && s.model); - if (withModel.length > 0) { - sessionModule.createDirectChat(withModel[0].endpoint_url, withModel[0].model, withModel[0].endpoint_id); - return; - } + if (await _createDirectChatFromPreferredModel()) return; // No models at all — show welcome screen sessionModule.setCurrentSessionId(null); if (documentModule && documentModule.isPanelOpen && documentModule.isPanelOpen()) documentModule.closePanel(); diff --git a/tests/test_new_chat_model_preference.py b/tests/test_new_chat_model_preference.py new file mode 100644 index 0000000..07e9b50 --- /dev/null +++ b/tests/test_new_chat_model_preference.py @@ -0,0 +1,44 @@ +from pathlib import Path + + +APP_JS = Path("static/app.js") + + +def _slice(source, start_marker, end_marker): + start = source.index(start_marker) + end = source.index(end_marker, start) + return source[start:end] + + +def test_new_chat_prefers_pending_and_current_model_before_default(): + source = APP_JS.read_text(encoding="utf-8") + helper = _slice( + source, + "async function _createDirectChatFromPreferredModel()", + "// ============================================", + ) + + default_pos = helper.index("const dc = await _refreshDefaultChat();") + assert helper.index("sessionModule.getPendingChat") < default_pos + assert helper.index("current.endpoint_url") < default_pos + assert default_pos < helper.index("const withModel = sessions.filter") + + +def test_desktop_new_chat_actions_use_shared_preference_helper(): + source = APP_JS.read_text(encoding="utf-8") + + rail_handler = _slice( + source, + "// New session button on icon rail", + "// Mobile new chat button", + ) + brand_handler = _slice( + source, + "// Logo click \u2192 new chat", + "const sidebarNewChatBtn = el('sidebar-new-chat-btn');", + ) + + assert "if (await _createDirectChatFromPreferredModel()) return;" in rail_handler + assert "if (await _createDirectChatFromPreferredModel()) return;" in brand_handler + assert "const dc = await _refreshDefaultChat();" not in rail_handler + assert "const dc = await _refreshDefaultChat();" not in brand_handler