improve reasoning toggle tests and refactor model capability checks

This commit is contained in:
2026-09-22 10:30:03 +02:00
parent a8e348e0c7
commit 3b6c8969cc
15 changed files with 201 additions and 23 deletions
+15 -6
View File
@@ -1,5 +1,6 @@
import {del, get, post, put, stream} from "./app/api.js?v=20260909-account-controls";
import {appendSources, createWebSearchToggle} from "./app/webSearch.js";
import {appendAttachments, createAttachmentComposer} from "./app/attachments.js";
import {createReasoningToggle, finishReasoning, updateReasoning} from "./app/reasoning.js?v=20260921-reasoning-capability";
import {closeChatDrawer, openChatDrawer} from "./app/chatDrawer.js?v=20260909-account-controls";
import {onboardingPrompts, requestedChatId} from "./app/constants.js?v=20260909-account-controls";
@@ -109,6 +110,7 @@ const webSearchToggle = createWebSearchToggle(webSearchButton);
const reasoningToggle = createReasoningToggle(document.getElementById("reasoning"));
let isProcessing = false, activeChatId = null, editingPersonaId = null, editingPersonaType = "assistant", currentUsername = "";
const attachmentComposer = createAttachmentComposer({onChange: updateSendState, onError: message => setNotice(message, "error")});
let chatSessions = [], currentMessages = [], assistantPersonas = [], userPersonas = [];
let activeUserPersonaId = null, currentSummary = null, publishedPersonaIds = new Set();
let popupResolver = null, popupMode = null, popupLastFocus = null;
@@ -329,7 +331,7 @@ function updateComposerPlaceholder() {
function updateSendState() {
const hasText = Boolean(msgInput.value.trim());
sendBtn.disabled = isProcessing ? false : !hasText;
sendBtn.disabled = isProcessing ? false : attachmentComposer.pending || (!hasText && !attachmentComposer.attachments.length);
sendBtn.setAttribute("aria-label", isProcessing ? "Stop generation" : "Send message");
}
@@ -742,7 +744,9 @@ function addMessage(contentOrMessage, isUser = false, isLoading = false, options
actions.append(prevBtn, indexBadge, nextBtn);
}
msgDiv.append(header, body);
msgDiv.append(header);
appendAttachments(msgDiv, message.attachments);
msgDiv.append(body);
if (!isMessageUser) updateReasoning(msgDiv, message.thinking);
if (!isMessageUser) appendSources(msgDiv, message.sources);
if (message.deliveryStatus === "failed" && message.errorMessage) {
@@ -1364,6 +1368,7 @@ function setLoadingState(loading, overlayOptions = null) {
msgInput.disabled = loading;
webSearchButton.disabled = loading;
reasoningToggle.setBusy(loading);
attachmentComposer.setBusy(loading);
sendBtn.classList.toggle("loading", loading);
messagesDiv.querySelectorAll('[data-message-action="regenerate"]').forEach((button) => {
button.disabled = loading || button.dataset.retryLimitReached === "true";
@@ -1811,7 +1816,9 @@ async function checkSession() {
async function sendMessage() {
if (isProcessing) return;
const message = msgInput.value.trim();
if (attachmentComposer.pending) return;
const attachments = attachmentComposer.attachments;
const message = msgInput.value.trim() || (attachments.length ? "Describe the attached images." : "");
if (!message) return;
const webSearch = webSearchToggle.enabled;
const reasoning = reasoningToggle.enabled;
@@ -1821,7 +1828,8 @@ async function sendMessage() {
const autoTitle = message.length > 40 ? `${message.slice(0, 40)}...` : message;
currentChat.title = autoTitle; updateWorkspaceCopy(); renderChatList(); await put(`/chats/${activeChatId}`, {title: autoTitle});
}
currentMessages.push({role: "user", content: message}); addMessage(message, true); updateChatActionState();
const userMessage = {role: "user", content: message, attachments};
currentMessages.push(userMessage); addMessage(userMessage, true); updateChatActionState();
msgInput.value = "";
resizeComposerInput();
setLoadingState(true, false); setNotice("Generating reply...");
@@ -1832,14 +1840,15 @@ async function sendMessage() {
loadingLabel.textContent = "Preparing response...";
try {
let streamError = null;
await stream("/chat/stream", {message, model: modelSelect.value, chatId: activeChatId, webSearch, reasoning}, {
await stream("/chat/stream", {message, attachments: attachments.map(item => item.id), model: modelSelect.value, chatId: activeChatId, webSearch, reasoning}, {
onStatus: ({status, sourceCount, searchState}) => {
if (status === "accepted") {
attachmentComposer.clear();
webSearchToggle.reset();
reasoningToggle.reset();
return;
}
loadingLabel.textContent = status === "searching" ? "Searching the web..."
loadingLabel.textContent = status === "analyzing" ? "Analyzing images..." : status === "searching" ? "Searching the web..."
: searchState === "no_relevant_results" ? "No sufficiently relevant results. Generating response..."
: sourceCount === 0 ? "No web results found. Generating response..." : "Generating response...";
},